From 12c5bd2305a83c65d068686ec2d6588bde769805 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 5 Dec 2006 01:55:02 -0500 Subject: [PATCH 01/41] Move the SyscallReturn class into sim/syscallreturn.hh. Also move some miscregs into the integer register file so they get renamed. src/arch/alpha/syscallreturn.hh: src/arch/mips/syscallreturn.hh: src/sim/syscallreturn.hh: Move the SyscallReturn class into sim/syscallreturn.hh src/arch/sparc/faults.cc: src/arch/sparc/isa/operands.isa: src/arch/sparc/isa_traits.hh: src/arch/sparc/miscregfile.cc: src/arch/sparc/miscregfile.hh: src/arch/sparc/process.cc: src/arch/sparc/sparc_traits.hh: Move some miscregs into the integer register file so they get renamed. --HG-- extra : convert_revision : df5b94fa1e7fdca34816084e0a423d6fdf86c79b --- src/arch/alpha/syscallreturn.hh | 33 +------------- src/arch/mips/syscallreturn.hh | 33 +------------- src/arch/sparc/faults.cc | 12 ++++-- src/arch/sparc/isa/operands.isa | 45 +++++++++++++------ src/arch/sparc/isa_traits.hh | 4 +- src/arch/sparc/miscregfile.cc | 76 ++++++++++++++++----------------- src/arch/sparc/miscregfile.hh | 14 +++--- src/arch/sparc/process.cc | 15 ++++--- src/arch/sparc/sparc_traits.hh | 3 +- src/arch/sparc/syscallreturn.hh | 50 +++++----------------- src/sim/syscallreturn.hh | 70 ++++++++++++++++++++++++++++++ 11 files changed, 182 insertions(+), 173 deletions(-) create mode 100644 src/sim/syscallreturn.hh diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh index 803c3b7da..88a6bf499 100644 --- a/src/arch/alpha/syscallreturn.hh +++ b/src/arch/alpha/syscallreturn.hh @@ -32,38 +32,7 @@ #ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__ #define __ARCH_ALPHA_SYSCALLRETURN_HH__ -class SyscallReturn { - public: - template - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template - 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; -}; +#include "sim/syscallreturn.hh" namespace AlphaISA { diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh index ef1093caf..0d36b3330 100644 --- a/src/arch/mips/syscallreturn.hh +++ b/src/arch/mips/syscallreturn.hh @@ -32,38 +32,7 @@ #ifndef __ARCH_MIPS_SYSCALLRETURN_HH__ #define __ARCH_MIPS_SYSCALLRETURN_HH__ -class SyscallReturn { - public: - template - SyscallReturn(T v, bool s) - { - retval = (uint32_t)v; - success = s; - } - - template - 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; -}; +#include "sim/syscallreturn.hh" namespace MipsISA { diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 9a29f24d5..67920a3d1 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -302,10 +302,12 @@ void doREDFault(ThreadContext *tc, TrapType tt) MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); MiscReg ASI = tc->readMiscReg(MISCREG_ASI); MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg CANSAVE = tc->readMiscReg(NumIntArchRegs + 3); MiscReg GL = tc->readMiscReg(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -396,10 +398,12 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); MiscReg ASI = tc->readMiscReg(MISCREG_ASI); MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); MiscReg GL = tc->readMiscReg(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 80ed7362c..9a5fda6ff 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -56,12 +56,23 @@ def operands {{ # Int regs default to unsigned, but code should not count on this. # For clarity, descriptions that depend on unsigned behavior should # explicitly specify '.uq'. + 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1), - 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2), - 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), - 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), - 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), - 'uReg0': ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 6), + # The Rd from the previous window + 'Rd_prev': ('IntReg', 'udw', 'RD + NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 2), + # The Rd from the next window + 'Rd_next': ('IntReg', 'udw', 'RD + 2 * NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 3), + # The low (even) register of a two register pair + 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 4), + # The high (odd) register of a two register pair + 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 5), + 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 6), + 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 7), + # A microcode register. Right now, this is the only one. + 'uReg0': ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 8), + # Because double and quad precision register numbers are decoded + # differently, they get different operands. The single precision versions + # have an s post pended to their name. 'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10), 'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10), # Each Frd_N refers to the Nth double precision register from Frd. @@ -80,14 +91,17 @@ def operands {{ 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12), 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), + # Registers which are used explicitly in instructions 'R0': ('IntReg', 'udw', '0', None, 6), 'R1': ('IntReg', 'udw', '1', None, 7), 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), 'R16': ('IntReg', 'udw', '16', None, 9), # Control registers - 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), - 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), +# 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), +# 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), + 'Y': ('IntReg', 'udw', 'NumIntArchRegs + 1', None, 40), + 'Ccr': ('IntReg', 'udw', 'NumIntArchRegs + 2', None, 41), 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42), 'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 43), 'Pcr': ('ControlReg', 'udw', 'MISCREG_PCR', None, 44), @@ -109,12 +123,17 @@ def operands {{ 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59), 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60), 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 62), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing']), 62), +# 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), +# 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), +# 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), +# 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66), +# 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67), + 'Cansave': ('IntReg', 'udw', 'NumIntArchRegs + 3', None, 63), + 'Canrestore': ('IntReg', 'udw', 'NumIntArchRegs + 4', None, 64), + 'Cleanwin': ('IntReg', 'udw', 'NumIntArchRegs + 5', None, 65), + 'Otherwin': ('IntReg', 'udw', 'NumIntArchRegs + 6', None, 66), + 'Wstate': ('IntReg', 'udw', 'NumIntArchRegs + 7', None, 67), 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68), 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69), diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 287f90658..7d786dc3b 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -58,8 +58,8 @@ namespace SparcISA // These enumerate all the registers for dependence tracking. enum DependenceTags { - FP_Base_DepTag = 33, - Ctrl_Base_DepTag = 97, + FP_Base_DepTag = 32*3+8, + Ctrl_Base_DepTag = FP_Base_DepTag + 64, }; // semantically meaningful register indices diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 7b0939c29..50a4f4871 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -50,12 +50,12 @@ class Checkpoint; string SparcISA::getMiscRegName(RegIndex index) { static::string miscRegName[NumMiscRegs] = - {"y", "ccr", "asi", "tick", "fprs", "pcr", "pic", + {/*"y", "ccr",*/ "asi", "tick", "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", + "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin", + "wstate",*/ "gl", "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", "hstick_cmpr", "fsr"}; @@ -109,10 +109,10 @@ void MiscRegFile::clear() MiscReg MiscRegFile::readReg(int miscReg) { switch (miscReg) { - case MISCREG_Y: - return y; - case MISCREG_CCR: - return ccr; +// case MISCREG_Y: +// return y; +// case MISCREG_CCR: +// return ccr; case MISCREG_ASI: return asi; case MISCREG_FPRS: @@ -155,16 +155,16 @@ MiscReg MiscRegFile::readReg(int miscReg) 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_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; @@ -225,12 +225,12 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) void MiscRegFile::setReg(int miscReg, const MiscReg &val) { switch (miscReg) { - case MISCREG_Y: - y = val; - break; - case MISCREG_CCR: - ccr = val; - break; +// case MISCREG_Y: +// y = val; +// break; +// case MISCREG_CCR: +// ccr = val; +// break; case MISCREG_ASI: asi = val; break; @@ -291,21 +291,21 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) case MISCREG_CWP: cwp = val; break; - case MISCREG_CANSAVE: - cansave = val; - break; - case MISCREG_CANRESTORE: - canrestore = val; - break; - case MISCREG_CLEANWIN: - cleanwin = val; - break; - case MISCREG_OTHERWIN: - otherwin = val; - break; - case MISCREG_WSTATE: - wstate = val; - break; +// case MISCREG_CANSAVE: +// cansave = val; +// break; +// case MISCREG_CANRESTORE: +// canrestore = val; +// break; +// case MISCREG_CLEANWIN: +// cleanwin = val; +// break; +// case MISCREG_OTHERWIN: +// otherwin = val; +// break; +// case MISCREG_WSTATE: +// wstate = val; +// break; case MISCREG_GL: gl = val; break; diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 6bc04b583..cf0405ac4 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -48,8 +48,8 @@ namespace SparcISA enum MiscRegIndex { /** Ancillary State Registers */ - MISCREG_Y, - MISCREG_CCR, +// MISCREG_Y, +// MISCREG_CCR, MISCREG_ASI, MISCREG_TICK, MISCREG_FPRS, @@ -74,11 +74,11 @@ namespace SparcISA MISCREG_TL, MISCREG_PIL, MISCREG_CWP, - MISCREG_CANSAVE, - MISCREG_CANRESTORE, - MISCREG_CLEANWIN, - MISCREG_OTHERWIN, - MISCREG_WSTATE, +// MISCREG_CANSAVE, +// MISCREG_CANRESTORE, +// MISCREG_CLEANWIN, +// MISCREG_OTHERWIN, +// MISCREG_WSTATE, MISCREG_GL, /** Hyper privileged registers */ diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 405e408e5..073117a84 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -95,17 +95,22 @@ SparcLiveProcess::startup() */ //No windows contain info from other programs - threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); + //threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); //There are no windows to pop - threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); + //threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); //All windows are available to save into - threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); + //threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); + threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); //All windows are "clean" - threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); + //threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); + threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); //Start with register window 0 threadContexts[0]->setMiscReg(MISCREG_CWP, 0); //Always use spill and fill traps 0 - threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + //threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); //Set the trap level to 0 threadContexts[0]->setMiscReg(MISCREG_TL, 0); //Set the ASI register to something fixed diff --git a/src/arch/sparc/sparc_traits.hh b/src/arch/sparc/sparc_traits.hh index a3d29ea8a..d89ec1119 100644 --- a/src/arch/sparc/sparc_traits.hh +++ b/src/arch/sparc/sparc_traits.hh @@ -41,7 +41,8 @@ namespace SparcISA // Number of register windows, can legally be 3 to 32 const int NWindows = 8; - const int NumMicroIntRegs = 1; + //const int NumMicroIntRegs = 1; + const int NumMicroIntRegs = 8; // const int NumRegularIntRegs = MaxGL * 8 + NWindows * 16; // const int NumMicroIntRegs = 1; diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh index 75a063da1..c2494c364 100644 --- a/src/arch/sparc/syscallreturn.hh +++ b/src/arch/sparc/syscallreturn.hh @@ -33,58 +33,30 @@ #include +#include "sim/syscallreturn.hh" #include "arch/sparc/regfile.hh" - -class SyscallReturn -{ - public: - template - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template - 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; -}; +#include "cpu/thread_context.hh" namespace SparcISA { static inline void setSyscallReturn(SyscallReturn return_value, - RegFile *regs) + ThreadContext * tc) { // 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) & 0xEE); - regs->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(NumIntArchRegs + 2, + tc->readIntReg(NumIntArchRegs + 2) & 0xEE); + //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) & 0xEE); + tc->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, set XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x11); - regs->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(NumIntArchRegs + 2, + tc->readIntReg(NumIntArchRegs + 2) | 0x11); + //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) | 0x11); + tc->setIntReg(ReturnValueReg, return_value.value()); } } }; diff --git a/src/sim/syscallreturn.hh b/src/sim/syscallreturn.hh new file mode 100644 index 000000000..d1c43f584 --- /dev/null +++ b/src/sim/syscallreturn.hh @@ -0,0 +1,70 @@ +/* + * 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 __SIM_SYSCALLRETURN_HH__ +#define __SIM_SYSCALLRETURN_HH__ + +#include + +class SyscallReturn +{ + public: + template + SyscallReturn(T v, bool s) + { + retval = (uint64_t)v; + success = s; + } + + template + 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 From a3f351ab595d61ddd7a3248fea5ddeea8c5ba65b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:40:11 -0500 Subject: [PATCH 02/41] Added basic flatten function for mips. --HG-- extra : convert_revision : 2c32851584001734d139f36c4d58c5e61067fcfc --- src/arch/mips/regfile/regfile.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index dee883c4a..7b57b31f5 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -173,6 +173,11 @@ namespace MipsISA } }; + static inline int flattenIntIndex(ThreadContext * tc, int reg) + { + return reg; + } + void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); From 4d8a0541dd16cf358c16dc8ad474717fcbed753f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:41:08 -0500 Subject: [PATCH 03/41] Change MIPS's setSyscallReturn to use a thread context. --HG-- extra : convert_revision : 618f8404ec5380615e28170d761b2fcdf9c07d96 --- src/arch/mips/syscallreturn.hh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh index 0d36b3330..47290b634 100644 --- a/src/arch/mips/syscallreturn.hh +++ b/src/arch/mips/syscallreturn.hh @@ -33,19 +33,21 @@ #define __ARCH_MIPS_SYSCALLRETURN_HH__ #include "sim/syscallreturn.hh" +#include "cpu/thread_context.hh" namespace MipsISA { - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + static inline void setSyscallReturn(SyscallReturn return_value, + ThreadContext *tc) { if (return_value.successful()) { // no error - regs->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg1, return_value.value()); + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg1, return_value.value()); } else { // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg) -1); - regs->setIntReg(ReturnValueReg1, -return_value.value()); + tc->setIntReg(SyscallSuccessReg, (IntReg) -1); + tc->setIntReg(ReturnValueReg1, -return_value.value()); } } } From c541be3a48dc8252fe26e020122039a5e9b9193c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:42:09 -0500 Subject: [PATCH 04/41] Changed the integer register file to work with flattened indices. --HG-- extra : convert_revision : c5153c3c712e5d18b5233e1fd205806adcb30654 --- src/arch/sparc/intregfile.cc | 9 +++++++++ src/arch/sparc/intregfile.hh | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 0a8ac055f..594fe4bea 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -66,6 +66,7 @@ void IntRegFile::clear() memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame); for(int x = 0; x < 2 * NWindows; x++) memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame); + memset(regs, 0, sizeof(IntReg) * NumIntRegs); } IntRegFile::IntRegFile() @@ -78,6 +79,8 @@ IntRegFile::IntRegFile() IntReg IntRegFile::readReg(int intReg) { + DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, regs[intReg]); + return regs[intReg]; IntReg val; if(intReg < NumIntArchRegs) val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; @@ -93,6 +96,12 @@ IntReg IntRegFile::readReg(int intReg) void IntRegFile::setReg(int intReg, const IntReg &val) { + if(intReg) + { + DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + regs[intReg] = val; + } + return; if(intReg) { DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 59f767e8e..503f3c453 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -34,6 +34,7 @@ #include "arch/sparc/isa_traits.hh" #include "arch/sparc/types.hh" +#include "base/bitfield.hh" #include @@ -54,15 +55,19 @@ namespace SparcISA private: friend class RegFile; protected: + //The number of bits needed to index into each 8 register frame static const int FrameOffsetBits = 3; + //The number of bits to choose between the 4 sets of 8 registers static const int FrameNumBits = 2; + //The number of registers per "frame" (8) static const int RegsPerFrame = 1 << FrameOffsetBits; - static const int FrameNumMask = + //A mask to get the frame number + static const uint64_t FrameNumMask = (FrameNumBits == sizeof(int)) ? (unsigned int)(-1) : (1 << FrameNumBits) - 1; - static const int FrameOffsetMask = + static const uint64_t FrameOffsetMask = (FrameOffsetBits == sizeof(int)) ? (unsigned int)(-1) : (1 << FrameOffsetBits) - 1; @@ -70,6 +75,7 @@ namespace SparcISA IntReg regGlobals[MaxGL][RegsPerFrame]; IntReg regSegments[2 * NWindows][RegsPerFrame]; IntReg microRegs[NumMicroIntRegs]; + IntReg regs[NumIntRegs]; enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; From a36a59e8d7c88f4eaa46384328496035116acb99 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:43:25 -0500 Subject: [PATCH 05/41] Some basic fix ups, and CWP is no longer set explicitly. --HG-- extra : convert_revision : 1dde5594a2bcfd9fb5ad974360b3dc035f1624e5 --- src/arch/sparc/isa/decoder.isa | 65 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 4e09e2e59..c3cff42ee 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -76,9 +76,15 @@ decode OP default Unknown::unknown() }}); 0x2: bpccx(19, {{ if(passesCondition(Ccr<7:4>, COND2)) + { + //warn("Took branch!\n"); NNPC = xc->readPC() + disp; + } else + { + //warn("Didn't take branch!\n"); handle_annul + } }}); } } @@ -247,16 +253,14 @@ decode OP default Unknown::unknown() ((Rs1 & val2) | (carryin & (Rs1 | val2)))<0:>)<63:>}}, {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} ); - 0x1A: umulcc({{ + 0x1A: IntOpCcRes::umulcc({{ uint64_t resTemp; Rd = resTemp = Rs1.udw<31:0> * Rs2_or_imm13.udw<31:0>; - Y = resTemp<63:32>;}}, - {{0}},{{0}},{{0}},{{0}}); - 0x1B: smulcc({{ + Y = resTemp<63:32>;}}); + 0x1B: IntOpCcRes::smulcc({{ int64_t resTemp; Rd = resTemp = Rs1.sdw<31:0> * Rs2_or_imm13.sdw<31:0>; - Y = resTemp<63:32>;}}, - {{0}},{{0}},{{0}},{{0}}); + Y = resTemp<63:32>;}}); 0x1C: subccc({{ int64_t resTemp, val2 = Rs2_or_imm13; int64_t carryin = Ccr<0:0>; @@ -266,10 +270,9 @@ decode OP default Unknown::unknown() {{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}}, {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}} ); - 0x1D: udivxcc({{ + 0x1D: IntOpCcRes::udivxcc({{ if(Rs2_or_imm13.udw == 0) fault = new DivisionByZero; - else Rd = Rs1.udw / Rs2_or_imm13.udw;}} - ,{{0}},{{0}},{{0}},{{0}}); + else Rd = Rs1.udw / Rs2_or_imm13.udw;}}); 0x1E: udivcc({{ uint32_t resTemp, val2 = Rs2_or_imm13.udw; int32_t overflow = 0; @@ -880,16 +883,11 @@ decode OP default Unknown::unknown() } }}); 0x39: Branch::return({{ - //If both MemAddressNotAligned and - //a fill trap happen, it's not clear - //which one should be returned. Addr target = Rs1 + Rs2_or_imm13; - if(target & 0x3) - fault = new MemAddressNotAligned; - else - NNPC = target; if(fault == NoFault) { + //Check for fills which are higher priority than alignment + //faults. if(Canrestore == 0) { if(Otherwin) @@ -897,18 +895,15 @@ decode OP default Unknown::unknown() else fault = new FillNNormal(Wstate<2:0>); } + //Check for alignment faults + else if(target & 0x3) + fault = new MemAddressNotAligned; else { - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one + NNPC = target; Cwp = (Cwp - 1 + NWindows) % NWindows; Cansave = Cansave + 1; Canrestore = Canrestore - 1; - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } } }}); @@ -926,7 +921,7 @@ decode OP default Unknown::unknown() xc->syscall(R1); #endif } - }}); + }}, IsSerializeAfter, IsNonSpeculative); 0x2: Trap::tccx({{ if(passesCondition(Ccr<7:4>, COND2)) { @@ -939,36 +934,27 @@ decode OP default Unknown::unknown() xc->syscall(R1); #endif } - }}); + }}, IsSerializeAfter, IsNonSpeculative); } 0x3B: Nop::flush({{/*Instruction memory flush*/}}); 0x3C: save({{ - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one if(Cansave == 0) { if(Otherwin) fault = new SpillNOther(Wstate<5:3>); else fault = new SpillNNormal(Wstate<2:0>); - //Cwp = (Cwp + 2) % NWindows; } else if(Cleanwin - Canrestore == 0) { - //Cwp = (Cwp + 1) % NWindows; fault = new CleanWindow; } else { Cwp = (Cwp + 1) % NWindows; - Rd = Rs1 + Rs2_or_imm13; + Rd_next = Rs1 + Rs2_or_imm13; Cansave = Cansave - 1; Canrestore = Canrestore + 1; - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } }}); 0x3D: restore({{ @@ -981,17 +967,10 @@ decode OP default Unknown::unknown() } else { - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one Cwp = (Cwp - 1 + NWindows) % NWindows; - Rd = Rs1 + Rs2_or_imm13; + Rd_prev = Rs1 + Rs2_or_imm13; Cansave = Cansave + 1; Canrestore = Canrestore - 1; - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } }}); 0x3E: decode FCN { From 643cb6dd819845cbc51b63cdc8b7baad89a99df4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:44:31 -0500 Subject: [PATCH 06/41] Added some debug output, and made sure not to accidentally ask for the result of a store conditional. --HG-- extra : convert_revision : d36ff9e2343fdf78a3bc16a1348975fdba5c55e2 --- src/arch/sparc/isa/formats/mem/util.isa | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index 857f37160..f3adbe19f 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -144,7 +144,7 @@ def template LoadExecute {{ %(op_decl)s; %(op_rd)s; %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -172,6 +172,7 @@ def template LoadExecute {{ %(ea_decl)s; %(ea_rd)s; %(ea_code)s; + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -202,7 +203,6 @@ def template StoreExecute {{ Trace::InstRecord *traceData) const { Fault fault = NoFault; - uint64_t write_result = 0; //This is to support the conditional store in cas instructions. //It should be optomized out in all the others bool storeCond = true; @@ -210,7 +210,7 @@ def template StoreExecute {{ %(op_decl)s; %(op_rd)s; %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -218,7 +218,7 @@ def template StoreExecute {{ } if(storeCond && fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); + fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, 0); } if(fault == NoFault) { @@ -233,13 +233,12 @@ def template StoreExecute {{ Trace::InstRecord * traceData) const { Fault fault = NoFault; - uint64_t write_result = 0; bool storeCond = true; Addr EA; %(op_decl)s; %(op_rd)s; %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -247,7 +246,7 @@ def template StoreExecute {{ } if(storeCond && fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); + fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, 0); } if(fault == NoFault) { From 5ad1731a1226a57780c34dc576e5ebdf6e1729f7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:45:18 -0500 Subject: [PATCH 07/41] Reorganize the includes and add an include for misc.hh. --HG-- extra : convert_revision : 484b2d07a1e8b3879c35d80bf16b73fd0cc9be1f --- src/arch/sparc/isa/includes.isa | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index 624afb693..2e7b16f20 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -37,12 +37,13 @@ output header {{ #include #include -#include "cpu/static_inst.hh" #include "arch/sparc/faults.hh" -#include "mem/request.hh" // some constructors use MemReq flags -#include "mem/packet.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/regfile.hh" +#include "base/misc.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/request.hh" // some constructors use MemReq flags }}; output decoder {{ From bf5f6c64305682d3e53a2cfe82ff6980c16341f4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:46:44 -0500 Subject: [PATCH 08/41] Some changes for misc regs which were changed into unofficial integer registers, and moved the flattenIndex function into the register file. --HG-- extra : convert_revision : 6b797c793a6c12c61a23f0f78a1ea1c88609553e --- src/arch/sparc/regfile.cc | 80 +++++++++++++++++++++++++++++++++++---- src/arch/sparc/regfile.hh | 2 + 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 06ba13423..29aca50c6 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -151,6 +151,72 @@ void RegFile::setIntReg(int intReg, const IntReg &val) intRegFile.setReg(intReg, val); } +int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) +{ + int gl = tc->readMiscReg(MISCREG_GL); + int cwp = tc->readMiscReg(MISCREG_CWP); + //DPRINTF(Sparc, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp); + int newReg; + if(reg < 8) + { + //Global register + //Put it in the appropriate set of globals + newReg = reg + gl * 8; + } + else if(reg < NumIntArchRegs) + { + //Regular windowed register + //Put it in the window pointed to by cwp + newReg = MaxGL * 8 + + ((reg - 8 - cwp * 16 + NWindows * 16) % (NWindows * 16)); + } + else if(reg < NumIntArchRegs + NumMicroIntRegs) + { + //Microcode register + //Displace from the end of the regular registers + newReg = reg - NumIntArchRegs + MaxGL * 8 + NWindows * 16; + } + else if(reg < 2 * NumIntArchRegs + NumMicroIntRegs) + { + reg -= (NumIntArchRegs + NumMicroIntRegs); + if(reg < 8) + { + //Global register from the next window + //Put it in the appropriate set of globals + newReg = reg + gl * 8; + } + else + { + //Windowed register from the previous window + //Put it in the window before the one pointed to by cwp + newReg = MaxGL * 8 + + ((reg - 8 - (cwp - 1) * 16 + NWindows * 16) % (NWindows * 16)); + } + } + else if(reg < 3 * NumIntArchRegs + NumMicroIntRegs) + { + reg -= (2 * NumIntArchRegs + NumMicroIntRegs); + if(reg < 8) + { + //Global register from the previous window + //Put it in the appropriate set of globals + newReg = reg + gl * 8; + } + else + { + //Windowed register from the next window + //Put it in the window after the one pointed to by cwp + newReg = MaxGL * 8 + + ((reg - 8 - (cwp + 1) * 16 + NWindows * 16) % (NWindows * 16)); + } + } + else + panic("Tried to flatten invalid register index %d!\n", reg); + DPRINTF(Sparc, "Flattened register %d to %d.\n", reg, newReg); + return newReg; + //return intRegFile.flattenIndex(reg); +} + void RegFile::serialize(std::ostream &os) { intRegFile.serialize(os); @@ -220,8 +286,8 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) // ASRs - dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y)); - dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR)); +// 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)); @@ -236,11 +302,11 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) 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_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 diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index 9f33435f6..51f1b5fef 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -120,6 +120,8 @@ namespace SparcISA void changeContext(RegContextParam param, RegContextVal val); }; + int flattenIntIndex(ThreadContext * tc, int reg); + void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); From dc105934f3771bd0cfb7407d339a0baed0028576 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:47:19 -0500 Subject: [PATCH 09/41] Change to use -return_value.value like other implementations. --HG-- extra : convert_revision : 513422c1c8c24f3662e6a423d13ee033424aa44b --- src/arch/sparc/syscallreturn.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh index c2494c364..d92b12790 100644 --- a/src/arch/sparc/syscallreturn.hh +++ b/src/arch/sparc/syscallreturn.hh @@ -56,7 +56,7 @@ namespace SparcISA tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) | 0x11); //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) | 0x11); - tc->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(ReturnValueReg, -return_value.value()); } } }; From 8a21635effac179a81b618cab3df7d028999e84f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:48:59 -0500 Subject: [PATCH 10/41] Get rid of some typedefs which were hardly used, and move some stuff back here that shouldn't be in the architecture specific DynInst classes. --HG-- extra : convert_revision : dad0d7191acf773c16dc3ed9dd911f5e8bfc08b3 --- src/cpu/base_dyn_inst.hh | 111 +++++++++++++++++++++++++++--- src/cpu/o3/mips/dyn_inst.hh | 82 +++------------------- src/cpu/o3/mips/dyn_inst_impl.hh | 4 +- src/cpu/o3/sparc/dyn_inst.hh | 82 ++++------------------ src/cpu/o3/sparc/dyn_inst_impl.hh | 4 +- 5 files changed, 131 insertions(+), 152 deletions(-) diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 4a4555566..0f7976631 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -39,6 +39,7 @@ #include "base/fast_alloc.hh" #include "base/trace.hh" #include "config/full_system.hh" +#include "cpu/o3/comm.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" #include "cpu/op_class.hh" @@ -62,10 +63,6 @@ class BaseDynInst : public FastAlloc, public RefCounted typedef typename Impl::CPUType ImplCPU; typedef typename ImplCPU::ImplState ImplState; - // 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 type. @@ -236,7 +233,105 @@ class BaseDynInst : public FastAlloc, public RefCounted */ bool _readySrcRegIdx[MaxInstSrcRegs]; + protected: + /** Flattened register index of the destination registers of this + * instruction. + */ + TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs]; + + /** Flattened register index of the source registers of this + * instruction. + */ + TheISA::RegIndex _flatSrcRegIdx[TheISA::MaxInstSrcRegs]; + + /** Physical register index of the destination registers of this + * instruction. + */ + PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs]; + + /** Physical register index of the source registers of this + * instruction. + */ + PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; + + /** Physical register index of the previous producers of the + * architected destinations. + */ + PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; + public: + + /** 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 flattened register index of the i'th destination + * register. + */ + TheISA::RegIndex flattenedDestRegIdx(int idx) const + { + return _flatDestRegIdx[idx]; + } + + /** Returns the flattened register index of the i'th source register */ + TheISA::RegIndex flattenedSrcRegIdx(int idx) const + { + return _flatSrcRegIdx[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; + } + + /** Flattens a source architectural register index into a logical index. + */ + void flattenSrcReg(int idx, TheISA::RegIndex flattened_src) + { + _flatSrcRegIdx[idx] = flattened_src; + } + + /** Flattens a destination architectural register index into a logical + * index. + */ + void flattenDestReg(int idx, TheISA::RegIndex flattened_dest) + { + _flatDestRegIdx[idx] = flattened_dest; + } + /** BaseDynInst constructor given a binary instruction. * @param inst The binary instruction. * @param PC The PC of the instruction. @@ -244,8 +339,8 @@ class BaseDynInst : public FastAlloc, public RefCounted * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num, - ImplCPU *cpu); + BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr pred_PC, + InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. * @param _staticInst The StaticInst for this BaseDynInst. @@ -298,9 +393,9 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns whether the instruction was predicted taken or not. */ bool predTaken() #if ISA_HAS_DELAY_SLOT - { return predPC != (nextPC + sizeof(MachInst)); } + { return predPC != (nextPC + sizeof(TheISA::MachInst)); } #else - { return predPC != (PC + sizeof(MachInst)); } + { return predPC != (PC + sizeof(TheISA::MachInst)); } #endif /** Returns whether the instruction mispredicted. */ diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index 9e95b2bfb..bf82168ce 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -54,10 +54,6 @@ class MipsDynInst : public BaseDynInst /** 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. */ @@ -127,22 +123,6 @@ class MipsDynInst : public BaseDynInst /** 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 @@ -158,27 +138,27 @@ class MipsDynInst : public BaseDynInst uint64_t readIntReg(const StaticInst *si, int idx) { - return this->cpu->readIntReg(_srcRegIdx[idx]); + return this->cpu->readIntReg(this->_srcRegIdx[idx]); } FloatReg readFloatReg(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatReg(_srcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } FloatReg readFloatReg(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(_srcRegIdx[idx]); + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -186,77 +166,35 @@ class MipsDynInst : public BaseDynInst */ void setIntReg(const StaticInst *si, int idx, uint64_t val) { - this->cpu->setIntReg(_destRegIdx[idx], val); + this->cpu->setIntReg(this->_destRegIdx[idx], val); BaseDynInst::setIntReg(si, idx, val); } void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { - this->cpu->setFloatReg(_destRegIdx[idx], val, width); + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); BaseDynInst::setFloatReg(si, idx, val, width); } void setFloatReg(const StaticInst *si, int idx, FloatReg val) { - this->cpu->setFloatReg(_destRegIdx[idx], val); + this->cpu->setFloatReg(this->_destRegIdx[idx], val); BaseDynInst::setFloatReg(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val, int width) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); BaseDynInst::setFloatRegBits(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); BaseDynInst::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 diff --git a/src/cpu/o3/mips/dyn_inst_impl.hh b/src/cpu/o3/mips/dyn_inst_impl.hh index 5bc01b9b3..fa8cf6cb4 100755 --- a/src/cpu/o3/mips/dyn_inst_impl.hh +++ b/src/cpu/o3/mips/dyn_inst_impl.hh @@ -53,11 +53,11 @@ MipsDynInst::initVars() // 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); + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); } for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); this->_readySrcRegIdx[i] = 0; } } diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index f8d6bb63f..c645b832b 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -32,6 +32,7 @@ #define __CPU_O3_SPARC_DYN_INST_HH__ #include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" #include "cpu/o3/sparc/cpu.hh" @@ -116,22 +117,6 @@ class SparcDynInst : public BaseDynInst void syscall(int64_t callnum); #endif - private: - /** Physical register index of the destination registers of this - * instruction. - */ - PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs]; - - /** Physical register index of the source registers of this - * instruction. - */ - PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; - - /** Physical register index of the previous producers of the - * architected destinations. - */ - PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; - public: // The register accessor methods provide the index of the @@ -147,28 +132,30 @@ class SparcDynInst : public BaseDynInst uint64_t readIntReg(const StaticInst *si, int idx) { - return this->cpu->readIntReg(_srcRegIdx[idx]); + uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]); + DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val); + return this->cpu->readIntReg(this->_srcRegIdx[idx]); } TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatReg(_srcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_flatSrcRegIdx[idx], width); } TheISA::FloatReg readFloatReg(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(_srcRegIdx[idx]); + return this->cpu->readFloatReg(this->_flatSrcRegIdx[idx]); } TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_flatSrcRegIdx[idx], width); } TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_flatSrcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -176,79 +163,38 @@ class SparcDynInst : public BaseDynInst */ void setIntReg(const StaticInst *si, int idx, uint64_t val) { - this->cpu->setIntReg(_destRegIdx[idx], val); + DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val); + this->cpu->setIntReg(this->_destRegIdx[idx], val); BaseDynInst::setIntReg(si, idx, val); } void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val, int width) { - this->cpu->setFloatReg(_destRegIdx[idx], val, width); + this->cpu->setFloatReg(this->_flatDestRegIdx[idx], val, width); BaseDynInst::setFloatReg(si, idx, val, width); } void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val) { - this->cpu->setFloatReg(_destRegIdx[idx], val); + this->cpu->setFloatReg(this->_flatDestRegIdx[idx], val); BaseDynInst::setFloatReg(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, TheISA::FloatRegBits val, int width) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->cpu->setFloatRegBits(this->_flatDestRegIdx[idx], val, width); BaseDynInst::setFloatRegBits(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, TheISA::FloatRegBits val) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(this->_flatDestRegIdx[idx], val); BaseDynInst::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 diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh index 210daace2..daf93d4a8 100644 --- a/src/cpu/o3/sparc/dyn_inst_impl.hh +++ b/src/cpu/o3/sparc/dyn_inst_impl.hh @@ -53,11 +53,11 @@ SparcDynInst::initVars() // 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); + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); } for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); this->_readySrcRegIdx[i] = 0; } } From 20340b5e26e05edd364eda5f69949cc8f957921b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:51:18 -0500 Subject: [PATCH 11/41] Change how optional delay slot instructions are detected and squashed. --HG-- extra : convert_revision : ffd019d4adc2fbbc0a663d8dc6ef73edce12511b --- src/cpu/o3/comm.hh | 2 +- src/cpu/o3/commit_impl.hh | 27 ++++++--------------------- src/cpu/o3/iew_impl.hh | 22 +++++++++++++++------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index aa58fc20e..4683c77af 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -87,7 +87,7 @@ struct DefaultIEWDefaultCommit { bool squash[Impl::MaxThreads]; bool branchMispredict[Impl::MaxThreads]; bool branchTaken[Impl::MaxThreads]; - bool condDelaySlotBranch[Impl::MaxThreads]; + bool squashDelaySlot[Impl::MaxThreads]; uint64_t mispredPC[Impl::MaxThreads]; uint64_t nextPC[Impl::MaxThreads]; InstSeqNum squashedSeqNum[Impl::MaxThreads]; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index e72679710..ba6a62b4d 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -728,27 +728,12 @@ DefaultCommit::commit() InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid]; #if ISA_HAS_DELAY_SLOT - InstSeqNum bdelay_done_seq_num; - bool squash_bdelay_slot; + InstSeqNum bdelay_done_seq_num = squashed_inst; + bool squash_bdelay_slot = fromIEW->squashDelaySlot[tid]; + + if (!squash_bdelay_slot) + bdelay_done_seq_num++; - 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) { @@ -1116,7 +1101,7 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Update the commit rename map for (int i = 0; i < head_inst->numDestRegs(); i++) { - renameMap[tid]->setEntry(head_inst->destRegIdx(i), + renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i), head_inst->renamedDestRegIdx(i)); } diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index ba5260fe2..85db68576 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -481,18 +481,26 @@ DefaultIEW::squashDueToBranch(DynInstPtr &inst, unsigned tid) toCommit->branchMispredict[tid] = true; #if ISA_HAS_DELAY_SLOT - bool branch_taken = inst->readNextNPC() != - (inst->readNextPC() + sizeof(TheISA::MachInst)); + bool branch_taken = + (inst->readNextNPC() != (inst->readPC() + 2 * sizeof(TheISA::MachInst)) && + inst->readNextNPC() != (inst->readPC() + 3 * sizeof(TheISA::MachInst))); + DPRINTF(Sparc, "Branch taken = %s [sn:%i]\n", + branch_taken ? "true": "false", inst->seqNum); toCommit->branchTaken[tid] = branch_taken; - toCommit->condDelaySlotBranch[tid] = inst->isCondDelaySlot(); - - if (inst->isCondDelaySlot() && branch_taken) { + bool squashDelaySlot = + (inst->readNextPC() != inst->readPC() + sizeof(TheISA::MachInst)); + DPRINTF(Sparc, "Squash delay slot = %s [sn:%i]\n", + squashDelaySlot ? "true": "false", inst->seqNum); + toCommit->squashDelaySlot[tid] = squashDelaySlot; + //If we're squashing the delay slot, we need to pick back up at NextPC. + //Otherwise, NextPC isn't being squashed, so we should pick back up at + //NextNPC. + if (squashDelaySlot) toCommit->nextPC[tid] = inst->readNextPC(); - } else { + else toCommit->nextPC[tid] = inst->readNextNPC(); - } #else toCommit->branchTaken[tid] = inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); From 6456cb535cce8b35c36fa0366fc8766ecffbbf44 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:54:16 -0500 Subject: [PATCH 12/41] Added in endianness conversion on memory accesses as the data goes out. This will break the checker! --HG-- extra : convert_revision : b8191cab09ab8f3ced05693293f058382319ed8e --- src/cpu/o3/lsq_unit_impl.hh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 4facea9f9..379724166 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -596,7 +596,11 @@ LSQUnit::writebackStores() assert(!inst->memData); inst->memData = new uint8_t[64]; - memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, + + TheISA::IntReg convertedData = + TheISA::htog(storeQueue[storeWBIdx].data); + + memcpy(inst->memData, (uint8_t *)&convertedData, req->getSize()); PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); From 156cf0db51e48acf12d1d3ca36c9827fea0e6b7d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:55:23 -0500 Subject: [PATCH 13/41] Change rename to rename the flattened register index instead of the architectural one. --HG-- extra : convert_revision : 757866ad7a3c8be7382e1ffa71c60bc00c861f6f --- src/cpu/o3/rename_impl.hh | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 248d7deb6..84ccf6d5b 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -31,6 +31,8 @@ #include +#include "arch/isa_traits.hh" +#include "arch/regfile.hh" #include "config/full_system.hh" #include "cpu/o3/rename.hh" @@ -960,13 +962,19 @@ DefaultRename::renameSrcRegs(DynInstPtr &inst,unsigned tid) // Will need to mark dependencies though. for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { RegIndex src_reg = inst->srcRegIdx(src_idx); + RegIndex flat_src_reg = src_reg; + if (src_reg < TheISA::FP_Base_DepTag) { + flat_src_reg = TheISA::flattenIntIndex(inst->tcBase(), src_reg); + DPRINTF(Rename, "Flattening index %d to %d.\n", (int)src_reg, (int)flat_src_reg); + } + inst->flattenSrcReg(src_idx, flat_src_reg); // Look up the source registers to get the phys. register they've // been renamed to, and set the sources to those registers. - PhysRegIndex renamed_reg = renameMap[tid]->lookup(src_reg); + PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg); DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got " - "physical reg %i.\n", tid, (int)src_reg, + "physical reg %i.\n", tid, (int)flat_src_reg, (int)renamed_reg); inst->renameSrcReg(src_idx, renamed_reg); @@ -993,20 +1001,27 @@ DefaultRename::renameDestRegs(DynInstPtr &inst,unsigned tid) // Rename the destination registers. for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) { RegIndex dest_reg = inst->destRegIdx(dest_idx); + RegIndex flat_dest_reg = dest_reg; + if (dest_reg < TheISA::FP_Base_DepTag) { + flat_dest_reg = TheISA::flattenIntIndex(inst->tcBase(), dest_reg); + DPRINTF(Rename, "Flattening index %d to %d.\n", (int)dest_reg, (int)flat_dest_reg); + } + + inst->flattenDestReg(dest_idx, flat_dest_reg); // Get the physical register that the destination will be // renamed to. - rename_result = renameMap[tid]->rename(dest_reg); + rename_result = renameMap[tid]->rename(flat_dest_reg); //Mark Scoreboard entry as not ready scoreboard->unsetReg(rename_result.first); DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " - "reg %i.\n", tid, (int)dest_reg, + "reg %i.\n", tid, (int)flat_dest_reg, (int)rename_result.first); // Record the rename information so that a history can be kept. - RenameHistory hb_entry(inst->seqNum, dest_reg, + RenameHistory hb_entry(inst->seqNum, flat_dest_reg, rename_result.first, rename_result.second); From 1d7d7df315e3bd9ddb3eedfed7f612e83778c252 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:56:34 -0500 Subject: [PATCH 14/41] Make syscalls flatten their register indices, and also call into the ISA's setSyscallReturn function rather than having a duplicated one. --HG-- extra : convert_revision : 1e83ef629a7fd143f2e35e68abaa56f81d6b9d9e --- src/cpu/o3/sparc/cpu_impl.hh | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh index 536a620bf..f92d863cc 100644 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -285,35 +285,24 @@ template TheISA::IntReg SparcO3CPU::getSyscallArg(int i, int tid) { - return this->readArchIntReg(SparcISA::ArgumentReg0 + i, tid); + IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + SparcISA::ArgumentReg0 + i); + return this->readArchIntReg(idx, tid); } template void SparcO3CPU::setSyscallArg(int i, IntReg val, int tid) { - this->setArchIntReg(SparcISA::ArgumentReg0 + i, val, tid); + IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + SparcISA::ArgumentReg0 + i); + this->setArchIntReg(idx, val, tid); } template void SparcO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) { - // 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 - this->setMiscReg(SparcISA::MISCREG_CCR, - this->readMiscReg(SparcISA::MISCREG_CCR, tid) & 0xEE, tid); - this->setArchIntReg(SparcISA::ReturnValueReg, - return_value.value(), tid); - } else { - // got an error, set XCC.C - this->setMiscReg(SparcISA::MISCREG_CCR, - this->readMiscReg(SparcISA::MISCREG_CCR, tid) | 0x11, tid); - this->setArchIntReg(SparcISA::ReturnValueReg, - return_value.value(), tid); - } + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); } #endif From 1886795368e0f07875f8f7ff70f09a8e200e6a85 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 05:58:07 -0500 Subject: [PATCH 15/41] Don't panic, but this needs to be fixed. --HG-- extra : convert_revision : 7a4aed238d437dbb2cc5946b3045d53697070a27 --- src/cpu/o3/sparc/thread_context.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/o3/sparc/thread_context.hh b/src/cpu/o3/sparc/thread_context.hh index 69d1e2d04..3955de0cc 100644 --- a/src/cpu/o3/sparc/thread_context.hh +++ b/src/cpu/o3/sparc/thread_context.hh @@ -62,7 +62,7 @@ class SparcTC : public O3ThreadContext virtual void changeRegFileContext(TheISA::RegContextParam param, TheISA::RegContextVal val) { - panic("This doesn't make sense!\n"); + //XXX Ignore this for now. This -really- needs to get fixed. } From 75b93179ab96de17c1ea62c3928d5fca9d5eb1be Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 06:00:04 -0500 Subject: [PATCH 16/41] Flattening and syscallReturn fixes src/cpu/o3/thread_context_impl.hh: Use flattened indices src/cpu/simple_thread.hh: Use flattened indices, and pass a thread context to setSyscallReturn rather than a register file. src/cpu/thread_context.hh: The SyscallReturn class is no longer in arch/syscallreturn.hh --HG-- extra : convert_revision : ed84bb8ac5ef0774526ecd0d7270b0c60cd3708e --- src/cpu/o3/thread_context_impl.hh | 3 +++ src/cpu/simple_thread.hh | 14 +++++++++----- src/cpu/thread_context.hh | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 0180756e3..29c00a0c3 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -29,6 +29,7 @@ * Korey Sewell */ +#include "arch/regfile.hh" #include "cpu/o3/thread_context.hh" #include "cpu/quiesce_event.hh" @@ -303,6 +304,7 @@ template uint64_t O3ThreadContext::readIntReg(int reg_idx) { + reg_idx = TheISA::flattenIntIndex(this, reg_idx); return cpu->readArchIntReg(reg_idx, thread->readTid()); } @@ -347,6 +349,7 @@ template void O3ThreadContext::setIntReg(int reg_idx, uint64_t val) { + reg_idx = TheISA::flattenIntIndex(this, reg_idx); cpu->setArchIntReg(reg_idx, val, thread->readTid()); // Squash if we're not already in a state update mode. diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index e8757c8c2..acbefeb67 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -33,6 +33,8 @@ #define __CPU_SIMPLE_THREAD_HH__ #include "arch/isa_traits.hh" +#include "arch/regfile.hh" +#include "arch/syscallreturn.hh" #include "config/full_system.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" @@ -319,7 +321,7 @@ class SimpleThread : public ThreadState // uint64_t readIntReg(int reg_idx) { - return regs.readIntReg(reg_idx); + return regs.readIntReg(TheISA::flattenIntIndex(getTC(), reg_idx)); } FloatReg readFloatReg(int reg_idx, int width) @@ -344,7 +346,7 @@ class SimpleThread : public ThreadState void setIntReg(int reg_idx, uint64_t val) { - regs.setIntReg(reg_idx, val); + regs.setIntReg(TheISA::flattenIntIndex(getTC(), reg_idx), val); } void setFloatReg(int reg_idx, FloatReg val, int width) @@ -445,18 +447,20 @@ class SimpleThread : public ThreadState #if !FULL_SYSTEM TheISA::IntReg getSyscallArg(int i) { - return regs.readIntReg(TheISA::ArgumentReg0 + i); + return regs.readIntReg(TheISA::flattenIntIndex(getTC(), + TheISA::ArgumentReg0 + i)); } // used to shift args for indirect syscall void setSyscallArg(int i, TheISA::IntReg val) { - regs.setIntReg(TheISA::ArgumentReg0 + i, val); + regs.setIntReg(TheISA::flattenIntIndex(getTC(), + TheISA::ArgumentReg0 + i), val); } void setSyscallReturn(SyscallReturn return_value) { - TheISA::setSyscallReturn(return_value, ®s); + TheISA::setSyscallReturn(return_value, getTC()); } void syscall(int64_t callnum) diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index baeb7a8be..2540df46b 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -32,13 +32,13 @@ #define __CPU_THREAD_CONTEXT_HH__ #include "arch/regfile.hh" -#include "arch/syscallreturn.hh" #include "arch/types.hh" #include "config/full_system.hh" #include "mem/request.hh" #include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" +#include "sim/syscallreturn.hh" #include "sim/byteswap.hh" // @todo: Figure out a more architecture independent way to obtain the ITB and From be29adf51cb115e7e55321bd58b7f6593e6d0080 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 06:02:13 -0500 Subject: [PATCH 17/41] Added a DPRINTF to print out the actual value pulled from memory. --HG-- extra : convert_revision : 18780f753a7e98f8de3047dd6781b944b0826b4e --- src/cpu/o3/fetch_impl.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 63d22b293..8213e8fa2 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1155,6 +1155,8 @@ DefaultFetch::fetch(bool &status_change) "[sn:%lli]\n", tid, instruction->readPC(), inst_seq); + DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst); + DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, instruction->staticInst->disassemble(fetch_PC)); From b3cfa6ec42a232bc31adb6cf540717859ad0fab3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:30:41 -0500 Subject: [PATCH 18/41] Added a flattenIntIndex function for Alpha. --HG-- extra : convert_revision : 5ed79ed18e443118a28d6890327c55a6a3fcd325 --- src/arch/alpha/regfile.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index ff5830822..c73c32bad 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -189,6 +189,11 @@ namespace AlphaISA } }; + static inline int flattenIntIndex(ThreadContext * tc, int reg) + { + return reg; + } + void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); From 0ed6c52c1ee061611dd95c2ebc4b4916e8641fc5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:33:37 -0500 Subject: [PATCH 19/41] Made the alpha setSyscallReturn take a ThreadContext pointer instead of a RegFile *. --HG-- extra : convert_revision : 021a1fe6760df1daf6299d46060371a5310f008a --- src/arch/alpha/syscallreturn.hh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh index 88a6bf499..47b4ac8c7 100644 --- a/src/arch/alpha/syscallreturn.hh +++ b/src/arch/alpha/syscallreturn.hh @@ -32,23 +32,25 @@ #ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__ #define __ARCH_ALPHA_SYSCALLRETURN_HH__ +#include "cpu/thread_context.hh" #include "sim/syscallreturn.hh" namespace AlphaISA { - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + static inline void setSyscallReturn(SyscallReturn return_value, + ThreadContext * tc) { // 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()); + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg)-1); - regs->setIntReg(ReturnValueReg, -return_value.value()); + tc->setIntReg(SyscallSuccessReg, (IntReg)-1); + tc->setIntReg(ReturnValueReg, -return_value.value()); } } } From 6826ee53dbab2e1a762aebb478a1c41389a4d07c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:36:40 -0500 Subject: [PATCH 20/41] Got rid of some typedefs, moved the tlbs to the base o3 cpu, and called the architecture defined setSyscallReturn function instead of a duplicate copy. src/cpu/o3/alpha/cpu.hh: Got rid of some typedefs, and moved the tlbs to the base o3 cpu. src/cpu/o3/alpha/thread_context.hh: src/cpu/o3/cpu.cc: Moved the tlbs to the base o3 cpu. --HG-- extra : convert_revision : 1805613aa230b8974a226ee3d2584c85f7a578aa --- src/cpu/o3/alpha/cpu.hh | 41 ++++++++---------------------- src/cpu/o3/alpha/cpu_impl.hh | 29 +++++---------------- src/cpu/o3/alpha/thread_context.hh | 6 ----- src/cpu/o3/cpu.cc | 4 +++ src/cpu/o3/cpu.hh | 24 +++++++++-------- 5 files changed, 35 insertions(+), 69 deletions(-) diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index 0078db69f..4a2086296 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -37,12 +37,6 @@ #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" -namespace TheISA -{ - class ITB; - class DTB; -} - class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -61,14 +55,6 @@ class TranslatingPort; template class AlphaO3CPU : public FullO3CPU { - protected: - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - typedef TheISA::MiscReg MiscReg; - typedef TheISA::RegFile RegFile; - typedef TheISA::MiscRegFile MiscRegFile; - public: typedef O3ThreadState ImplState; typedef O3ThreadState Thread; @@ -77,13 +63,6 @@ class AlphaO3CPU : public FullO3CPU /** Constructs an AlphaO3CPU with the given parameters. */ AlphaO3CPU(Params *params); -#if FULL_SYSTEM - /** ITB pointer. */ - AlphaISA::ITB *itb; - /** DTB pointer. */ - AlphaISA::DTB *dtb; -#endif - /** Registers statistics. */ void regStats(); @@ -91,19 +70,19 @@ class AlphaO3CPU : public FullO3CPU /** Translates instruction requestion. */ Fault translateInstReq(RequestPtr &req, Thread *thread) { - return itb->translate(req, thread->getTC()); + return this->itb->translate(req, thread->getTC()); } /** Translates data read request. */ Fault translateDataReadReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), false); + return this->dtb->translate(req, thread->getTC(), false); } /** Translates data write request. */ Fault translateDataWriteReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), true); + return this->dtb->translate(req, thread->getTC(), true); } #else @@ -127,20 +106,22 @@ class AlphaO3CPU : public FullO3CPU #endif /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg, unsigned tid); + 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. */ - MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + void 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. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid); + void 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 @@ -175,10 +156,10 @@ class AlphaO3CPU : public FullO3CPU */ void syscall(int64_t callnum, int tid); /** Gets a syscall argument. */ - IntReg getSyscallArg(int i, int tid); + TheISA::IntReg getSyscallArg(int i, int tid); /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, IntReg val, int tid); + void setSyscallArg(int i, TheISA::IntReg val, int tid); /** Sets the return value of a syscall. */ void setSyscallReturn(SyscallReturn return_value, int tid); diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 98fd0699a..fb0962056 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -55,12 +55,7 @@ #endif template -AlphaO3CPU::AlphaO3CPU(Params *params) -#if FULL_SYSTEM - : FullO3CPU(params), itb(params->itb), dtb(params->dtb) -#else - : FullO3CPU(params) -#endif +AlphaO3CPU::AlphaO3CPU(Params *params) : FullO3CPU(params) { DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n"); @@ -173,15 +168,16 @@ AlphaO3CPU::readMiscRegWithEffect(int misc_reg, unsigned tid) template void -AlphaO3CPU::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +AlphaO3CPU::setMiscReg(int misc_reg, const TheISA::MiscReg &val, + unsigned tid) { this->regFile.setMiscReg(misc_reg, val, tid); } template void -AlphaO3CPU::setMiscRegWithEffect(int misc_reg, const MiscReg &val, - unsigned tid) +AlphaO3CPU::setMiscRegWithEffect(int misc_reg, + const TheISA::MiscReg &val, unsigned tid) { this->regFile.setMiscRegWithEffect(misc_reg, val, tid); } @@ -315,7 +311,7 @@ AlphaO3CPU::getSyscallArg(int i, int tid) template void -AlphaO3CPU::setSyscallArg(int i, IntReg val, int tid) +AlphaO3CPU::setSyscallArg(int i, TheISA::IntReg val, int tid) { this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid); } @@ -324,17 +320,6 @@ template void AlphaO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) { - // 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 - this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid); - this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid); - } else { - // got an error, return details - this->setArchIntReg(TheISA::SyscallSuccessReg, (IntReg) -1, tid); - this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid); - } + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); } #endif diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh index bcecb7087..e4a6735c2 100644 --- a/src/cpu/o3/alpha/thread_context.hh +++ b/src/cpu/o3/alpha/thread_context.hh @@ -36,12 +36,6 @@ class AlphaTC : public O3ThreadContext { public: #if FULL_SYSTEM - /** Returns a pointer to the ITB. */ - virtual AlphaISA::ITB *getITBPtr() { return this->cpu->itb; } - - /** Returns a pointer to the DTB. */ - virtual AlphaISA::DTB *getDTBPtr() { return this->cpu->dtb; } - /** Returns pointer to the quiesce event. */ virtual EndQuiesceEvent *getQuiesceEvent() { diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index a5a00015f..4056d876f 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -149,6 +149,10 @@ FullO3CPU::DeallocateContextEvent::description() template FullO3CPU::FullO3CPU(Params *params) : BaseO3CPU(params), +#if FULL_SYSTEM + itb(params->itb), + dtb(params->dtb), +#endif tickEvent(this), removeInstsThisCycle(false), fetch(params), diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 2bf9cb23b..d217a3e85 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -91,9 +91,6 @@ template class FullO3CPU : public BaseO3CPU { public: - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - // Typedefs from the Impl here. typedef typename Impl::CPUPol CPUPolicy; typedef typename Impl::Params Params; @@ -114,6 +111,11 @@ class FullO3CPU : public BaseO3CPU SwitchedOut }; +#if FULL_SYSTEM + TheISA::ITB * itb; + TheISA::DTB * dtb; +#endif + /** Overall CPU status. */ Status _status; @@ -382,23 +384,23 @@ class FullO3CPU : public BaseO3CPU /** Register accessors. Index refers to the physical register index. */ uint64_t readIntReg(int reg_idx); - FloatReg readFloatReg(int reg_idx); + TheISA::FloatReg readFloatReg(int reg_idx); - FloatReg readFloatReg(int reg_idx, int width); + TheISA::FloatReg readFloatReg(int reg_idx, int width); - FloatRegBits readFloatRegBits(int reg_idx); + TheISA::FloatRegBits readFloatRegBits(int reg_idx); - FloatRegBits readFloatRegBits(int reg_idx, int width); + TheISA::FloatRegBits readFloatRegBits(int reg_idx, int width); void setIntReg(int reg_idx, uint64_t val); - void setFloatReg(int reg_idx, FloatReg val); + void setFloatReg(int reg_idx, TheISA::FloatReg val); - void setFloatReg(int reg_idx, FloatReg val, int width); + void setFloatReg(int reg_idx, TheISA::FloatReg val, int width); - void setFloatRegBits(int reg_idx, FloatRegBits val); + void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val); - void setFloatRegBits(int reg_idx, FloatRegBits val, int width); + void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val, int width); uint64_t readArchIntReg(int reg_idx, unsigned tid); From ef942ceecba7ca1affee5545ba9004d32d1e8536 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:37:39 -0500 Subject: [PATCH 21/41] Moved the RegIdx arrays to the base dyninst. --HG-- extra : convert_revision : d705cde25c2cf1add20669e99d086add49141518 --- src/cpu/o3/alpha/dyn_inst.hh | 78 ++++--------------------------- src/cpu/o3/alpha/dyn_inst_impl.hh | 4 +- 2 files changed, 12 insertions(+), 70 deletions(-) diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index 31df8ff78..4e2ce63df 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -134,22 +134,6 @@ class AlphaDynInst : public BaseDynInst void syscall(int64_t callnum); #endif - 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 @@ -165,27 +149,27 @@ class AlphaDynInst : public BaseDynInst uint64_t readIntReg(const StaticInst *si, int idx) { - return this->cpu->readIntReg(_srcRegIdx[idx]); + return this->cpu->readIntReg(this->_srcRegIdx[idx]); } FloatReg readFloatReg(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatReg(_srcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } FloatReg readFloatReg(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(_srcRegIdx[idx]); + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -193,77 +177,35 @@ class AlphaDynInst : public BaseDynInst */ void setIntReg(const StaticInst *si, int idx, uint64_t val) { - this->cpu->setIntReg(_destRegIdx[idx], val); + this->cpu->setIntReg(this->_destRegIdx[idx], val); BaseDynInst::setIntReg(si, idx, val); } void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { - this->cpu->setFloatReg(_destRegIdx[idx], val, width); + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); BaseDynInst::setFloatReg(si, idx, val, width); } void setFloatReg(const StaticInst *si, int idx, FloatReg val) { - this->cpu->setFloatReg(_destRegIdx[idx], val); + this->cpu->setFloatReg(this->_destRegIdx[idx], val); BaseDynInst::setFloatReg(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val, int width) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); BaseDynInst::setFloatRegBits(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); BaseDynInst::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 diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index 6fc548a85..02432f721 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -53,11 +53,11 @@ AlphaDynInst::initVars() // 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); + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); } for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); this->_readySrcRegIdx[i] = 0; } } From 07a4e2cd36c35ab7b6be356d9bcf3b58b5ef6794 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:38:39 -0500 Subject: [PATCH 22/41] Use the setSyscallReturn defined in arch rather than duplicating it here. --HG-- extra : convert_revision : 862ece59aa253b52b6744a0a76738d5ee19561b3 --- src/cpu/o3/mips/cpu_impl.hh | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh index 08e9ba483..e7dbd3aba 100644 --- a/src/cpu/o3/mips/cpu_impl.hh +++ b/src/cpu/o3/mips/cpu_impl.hh @@ -220,16 +220,6 @@ template void MipsO3CPU::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); - } + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); } #endif From f04fcf58f1dc7adcf67e19ca00ff741775982dfa Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:39:49 -0500 Subject: [PATCH 23/41] Got rid of some typedefs and moved the tlbs into the base o3 cpu. --HG-- extra : convert_revision : dcd1d2a64fd91aded15c8c763a78b4eebf421870 --- src/cpu/o3/sparc/cpu.hh | 60 ++++++------------------------ src/cpu/o3/sparc/cpu_impl.hh | 20 ++++------ src/cpu/o3/sparc/thread_context.hh | 6 --- src/cpu/o3/thread_context.hh | 8 ++++ 4 files changed, 27 insertions(+), 67 deletions(-) diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index c4df79832..73c859367 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -37,12 +37,6 @@ #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" -namespace TheISA -{ - class ITB; - class DTB; -} - class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -61,14 +55,6 @@ class TranslatingPort; template class SparcO3CPU : public FullO3CPU { - protected: - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - typedef TheISA::MiscReg MiscReg; - typedef TheISA::RegFile RegFile; - typedef TheISA::MiscRegFile MiscRegFile; - public: typedef O3ThreadState ImplState; typedef O3ThreadState Thread; @@ -77,13 +63,6 @@ class SparcO3CPU : public FullO3CPU /** Constructs an AlphaO3CPU with the given parameters. */ SparcO3CPU(Params *params); -#if FULL_SYSTEM - /** ITB pointer. */ - SparcISA::ITB *itb; - /** DTB pointer. */ - SparcISA::DTB *dtb; -#endif - /** Registers statistics. */ void regStats(); @@ -91,19 +70,19 @@ class SparcO3CPU : public FullO3CPU /** Translates instruction requestion. */ Fault translateInstReq(RequestPtr &req, Thread *thread) { - return itb->translate(req, thread->getTC()); + return this->itb->translate(req, thread->getTC()); } /** Translates data read request. */ Fault translateDataReadReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), false); + return this->dtb->translate(req, thread->getTC(), false); } /** Translates data write request. */ Fault translateDataWriteReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), true); + return this->dtb->translate(req, thread->getTC(), true); } #else @@ -127,20 +106,21 @@ class SparcO3CPU : public FullO3CPU #endif /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg, unsigned tid); + 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. */ - MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + void 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. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid); + void 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 @@ -148,24 +128,6 @@ class SparcO3CPU : public FullO3CPU */ void squashFromTC(unsigned tid); -#if FULL_SYSTEM - /** Posts an interrupt. */ - void post_interrupt(int int_num, int index); - /** HW return from error interrupt. */ - Fault hwrei(unsigned tid); - - bool simPalCheck(int palFunc, unsigned tid); - - /** Returns the Fault for any valid interrupt. */ - Fault getInterrupts(); - - /** Processes any an interrupt fault. */ - void processInterrupts(Fault interrupt); - - /** Halts the CPU. */ - void halt() { panic("Halt not implemented!\n"); } -#endif - /** Traps to handle given fault. */ void trap(Fault fault, unsigned tid); @@ -175,10 +137,10 @@ class SparcO3CPU : public FullO3CPU */ void syscall(int64_t callnum, int tid); /** Gets a syscall argument. */ - IntReg getSyscallArg(int i, int tid); + TheISA::IntReg getSyscallArg(int i, int tid); /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, IntReg val, int tid); + void setSyscallArg(int i, TheISA::IntReg val, int tid); /** Sets the return value of a syscall. */ void setSyscallReturn(SyscallReturn return_value, int tid); @@ -204,4 +166,4 @@ class SparcO3CPU : public FullO3CPU bool lockFlag; }; -#endif // __CPU_O3_ALPHA_CPU_HH__ +#endif // __CPU_O3_SPARC_CPU_HH__ diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh index f92d863cc..4a194cbda 100644 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -55,12 +55,7 @@ #endif template -SparcO3CPU::SparcO3CPU(Params *params) -#if FULL_SYSTEM - : FullO3CPU(params), itb(params->itb), dtb(params->dtb) -#else - : FullO3CPU(params) -#endif +SparcO3CPU::SparcO3CPU(Params *params) : FullO3CPU(params) { DPRINTF(O3CPU, "Creating SparcO3CPU object.\n"); @@ -172,15 +167,16 @@ SparcO3CPU::readMiscRegWithEffect(int misc_reg, unsigned tid) template void -SparcO3CPU::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +SparcO3CPU::setMiscReg(int misc_reg, + const SparcISA::MiscReg &val, unsigned tid) { this->regFile.setMiscReg(misc_reg, val, tid); } template void -SparcO3CPU::setMiscRegWithEffect(int misc_reg, const MiscReg &val, - unsigned tid) +SparcO3CPU::setMiscRegWithEffect(int misc_reg, + const SparcISA::MiscReg &val, unsigned tid) { this->regFile.setMiscRegWithEffect(misc_reg, val, tid); } @@ -285,16 +281,16 @@ template TheISA::IntReg SparcO3CPU::getSyscallArg(int i, int tid) { - IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), SparcISA::ArgumentReg0 + i); return this->readArchIntReg(idx, tid); } template void -SparcO3CPU::setSyscallArg(int i, IntReg val, int tid) +SparcO3CPU::setSyscallArg(int i, TheISA::IntReg val, int tid) { - IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), SparcISA::ArgumentReg0 + i); this->setArchIntReg(idx, val, tid); } diff --git a/src/cpu/o3/sparc/thread_context.hh b/src/cpu/o3/sparc/thread_context.hh index 3955de0cc..7497959e4 100644 --- a/src/cpu/o3/sparc/thread_context.hh +++ b/src/cpu/o3/sparc/thread_context.hh @@ -36,12 +36,6 @@ class SparcTC : public O3ThreadContext { public: #if FULL_SYSTEM - /** Returns a pointer to the ITB. */ - virtual SparcISA::ITB *getITBPtr() { return this->cpu->itb; } - - /** Returns a pointer to the DTB. */ - virtual SparcISA::DTB *getDTBPtr() { return this->cpu->dtb; } - /** Returns pointer to the quiesce event. */ virtual EndQuiesceEvent *getQuiesceEvent() { diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 390569c3d..0849001e8 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -66,6 +66,14 @@ class O3ThreadContext : public ThreadContext /** Pointer to the thread state that this TC corrseponds to. */ O3ThreadState *thread; +#if FULL_SYSTEM + /** Returns a pointer to the ITB. */ + virtual AlphaISA::ITB *getITBPtr() { return cpu->itb; } + + /** Returns a pointer to the DTB. */ + virtual AlphaISA::DTB *getDTBPtr() { return cpu->dtb; } +#endif + /** Returns a pointer to this CPU. */ virtual BaseCPU *getCpuPtr() { return cpu; } From 50b8cce355bc26a625e17a2651777340aa90a706 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 6 Dec 2006 11:40:41 -0500 Subject: [PATCH 24/41] Use the renamed register index, rather than the flattened one. --HG-- extra : convert_revision : 599650c408667bb1b8db20a6847b9e697f7b49e4 --- src/cpu/o3/sparc/dyn_inst.hh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index c645b832b..2d73ca8d1 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -139,23 +139,23 @@ class SparcDynInst : public BaseDynInst TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatReg(this->_flatSrcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } TheISA::FloatReg readFloatReg(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(this->_flatSrcRegIdx[idx]); + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(this->_flatSrcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(this->_flatSrcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -171,27 +171,27 @@ class SparcDynInst : public BaseDynInst void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val, int width) { - this->cpu->setFloatReg(this->_flatDestRegIdx[idx], val, width); + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); BaseDynInst::setFloatReg(si, idx, val, width); } void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val) { - this->cpu->setFloatReg(this->_flatDestRegIdx[idx], val); + this->cpu->setFloatReg(this->_destRegIdx[idx], val); BaseDynInst::setFloatReg(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, TheISA::FloatRegBits val, int width) { - this->cpu->setFloatRegBits(this->_flatDestRegIdx[idx], val, width); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); BaseDynInst::setFloatRegBits(si, idx, val); } void setFloatRegBits(const StaticInst *si, int idx, TheISA::FloatRegBits val) { - this->cpu->setFloatRegBits(this->_flatDestRegIdx[idx], val); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); BaseDynInst::setFloatRegBits(si, idx, val); } From 015873fa863bb5b84e3f6b826422007272e9921d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 7 Dec 2006 18:43:55 -0500 Subject: [PATCH 25/41] Change how Page Faults work in SPARC. It now prints the faulting address, and panics instead of fatals. This isn't technically what it should do, but it makes gdb stop at the panic rather than letting m5 exit. --HG-- extra : convert_revision : 3b14c99edaf649e0809977c9579afb2b7b0d72e9 --- src/arch/sparc/faults.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 67920a3d1..4326e8b67 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -690,19 +690,21 @@ void PageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); - // address is higher than the stack region or in the current stack region - if (vaddr > p->stack_base || vaddr > p->stack_min) - FaultBase::invoke(tc); - - // We've accessed the next page - if (vaddr > p->stack_min - PageBytes) { + // We've accessed the next page of the stack, so extend the stack + // to cover it. + if(vaddr < p->stack_min && vaddr >= p->stack_min - PageBytes) + { p->stack_min -= PageBytes; - if (p->stack_base - p->stack_min > 8*1024*1024) + if(p->stack_base - p->stack_min > 8*1024*1024) fatal("Over max stack size for one thread\n"); p->pTable->allocate(p->stack_min, PageBytes); warn("Increasing stack size by one page."); - } else { - FaultBase::invoke(tc); + } + // Otherwise, we have an unexpected page fault. Report that fact, + // and what address was accessed to cause the fault. + else + { + panic("Page table fault when accessing virtual address %#x\n", vaddr); } } From 41051f35acc36c0401eaf7312a284aef17e0f882 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 7 Dec 2006 18:45:30 -0500 Subject: [PATCH 26/41] Make branches handle the lack of a symbol table or the lack of a symbol gracefully. --HG-- extra : convert_revision : 7bb16405999b86f9fa082a6d44da43d346edc182 --- src/arch/sparc/isa/formats/branch.isa | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 5fb7ade2d..3062f38b2 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -170,7 +170,7 @@ output decoder {{ printMnemonic(response, mnemonic); ccprintf(response, "0x%x", target); - if(symtab->findNearestSymbol(target, symbol, symbolAddr)) + if(symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { ccprintf(response, " <%s", symbol); if(symbolAddr != target) @@ -178,6 +178,10 @@ output decoder {{ else ccprintf(response, ">"); } + else + { + ccprintf(response, "<%d>", target); + } return response.str(); } From 0f8fd5fd689a3631a5896a1c098e6e561aa6a80e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 7 Dec 2006 18:47:33 -0500 Subject: [PATCH 27/41] Fix for squashing during a serializing instruction. --HG-- extra : convert_revision : 04f9131258bfb7cca1654e00273edb29bde2366b --- src/cpu/o3/rename.hh | 4 ++++ src/cpu/o3/rename_impl.hh | 40 ++++++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 177b9cb87..1ede6f355 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -411,6 +411,10 @@ class DefaultRename /** Whether or not rename needs to block this cycle. */ bool blockThisCycle; + /** Whether or not rename needs to resume a serialize instruction + * after squashing. */ + bool resumeSerialize; + /** The number of threads active in rename. */ unsigned numThreads; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 84ccf6d5b..0c211b183 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -43,6 +43,7 @@ DefaultRename::DefaultRename(Params *params) commitToRenameDelay(params->commitToRenameDelay), renameWidth(params->renameWidth), commitWidth(params->commitWidth), + resumeSerialize(false), numThreads(params->numberOfThreads), maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs) { @@ -334,12 +335,22 @@ DefaultRename::squash(const InstSeqNum &squash_seq_num, unsigned tid) // If it still needs to block, the blocking should happen the next // cycle and there should be space to hold everything due to the squash. if (renameStatus[tid] == Blocked || - renameStatus[tid] == Unblocking || - renameStatus[tid] == SerializeStall) { - + renameStatus[tid] == Unblocking) { toDecode->renameUnblock[tid] = 1; + resumeSerialize = false; serializeInst[tid] = NULL; + } else if (renameStatus[tid] == SerializeStall) { + if (serializeInst[tid]->seqNum <= squash_seq_num) { + DPRINTF(Rename, "Rename will resume serializing after squash\n"); + resumeSerialize = true; + assert(serializeInst[tid]); + } else { + resumeSerialize = false; + toDecode->renameUnblock[tid] = 1; + + serializeInst[tid] = NULL; + } } // Set the status to Squashing. @@ -477,6 +488,14 @@ DefaultRename::rename(bool &status_change, unsigned tid) ++renameSquashCycles; } else if (renameStatus[tid] == SerializeStall) { ++renameSerializeStallCycles; + // If we are currently in SerializeStall and resumeSerialize + // was set, then that means that we are resuming serializing + // this cycle. Tell the previous stages to block. + if (resumeSerialize) { + resumeSerialize = false; + block(tid); + toDecode->renameUnblock[tid] = false; + } } if (renameStatus[tid] == Running || @@ -1245,12 +1264,19 @@ DefaultRename::checkSignalsAndUpdate(unsigned tid) if (renameStatus[tid] == Squashing) { // Switch status to running if rename isn't being told to block or // squash this cycle. - DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", - tid); + if (!resumeSerialize) { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", + tid); - renameStatus[tid] = Running; + renameStatus[tid] = Running; + return false; + } else { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n", + tid); - return false; + renameStatus[tid] = SerializeStall; + return true; + } } if (renameStatus[tid] == SerializeStall) { From 97cdd5198b9c1a5b881833a71f24a22430a2b07b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 7 Dec 2006 18:49:10 -0500 Subject: [PATCH 28/41] Compilation fixes --HG-- extra : convert_revision : 974e91a960251a35d5ebb76c7e6c7ac330339896 --- src/cpu/o3/sparc/cpu.hh | 18 ++++++++++++++++++ src/cpu/o3/sparc/cpu_builder.cc | 4 ++-- src/cpu/o3/sparc/dyn_inst_impl.hh | 3 ++- src/cpu/o3/thread_context.hh | 4 ++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index 73c859367..08ebd2710 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -128,6 +128,24 @@ class SparcO3CPU : public FullO3CPU */ void squashFromTC(unsigned tid); +#if FULL_SYSTEM + /** Posts an interrupt. */ + void post_interrupt(int int_num, int index); + /** HW return from error interrupt. */ + Fault hwrei(unsigned tid); + + bool simPalCheck(int palFunc, unsigned tid); + + /** Returns the Fault for any valid interrupt. */ + Fault getInterrupts(); + + /** Processes any an interrupt fault. */ + void processInterrupts(Fault interrupt); + + /** Halts the CPU. */ + void halt() { panic("Halt not implemented!\n"); } +#endif + /** Traps to handle given fault. */ void trap(Fault fault, unsigned tid); diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc index 81f419ee0..3cac89bad 100644 --- a/src/cpu/o3/sparc/cpu_builder.cc +++ b/src/cpu/o3/sparc/cpu_builder.cc @@ -55,8 +55,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU) #if FULL_SYSTEM SimObjectParam system; Param cpu_id; - SimObjectParam itb; - SimObjectParam dtb; + SimObjectParam itb; + SimObjectParam dtb; Param profile; Param do_quiesce; diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh index daf93d4a8..b830ee7bd 100644 --- a/src/cpu/o3/sparc/dyn_inst_impl.hh +++ b/src/cpu/o3/sparc/dyn_inst_impl.hh @@ -126,7 +126,8 @@ template bool SparcDynInst::simPalCheck(int palFunc) { - return this->cpu->simPalCheck(palFunc, this->threadNumber); + panic("simPalCheck called, but there's no PAL in SPARC!\n"); + return false; } #else template diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 0849001e8..4987d6eb4 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -68,10 +68,10 @@ class O3ThreadContext : public ThreadContext #if FULL_SYSTEM /** Returns a pointer to the ITB. */ - virtual AlphaISA::ITB *getITBPtr() { return cpu->itb; } + TheISA::ITB *getITBPtr() { return cpu->itb; } /** Returns a pointer to the DTB. */ - virtual AlphaISA::DTB *getDTBPtr() { return cpu->dtb; } + TheISA::DTB *getDTBPtr() { return cpu->dtb; } #endif /** Returns a pointer to this CPU. */ From 498e235ae0612d268001f813de6031fcdfc76de7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 7 Dec 2006 19:00:46 -0500 Subject: [PATCH 29/41] Fixed to take into account the misc regs that became int regs. --HG-- extra : convert_revision : b4f78f6e48fdd2f1774ba63b28615e0d2556b7b9 --- src/cpu/exetrace.cc | 48 ++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index f3b9b51b2..780a0c4f7 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -141,13 +141,15 @@ Trace::InstRecord::dump(ostream &outs) outs << hex; outs << "PC = " << thread->readNextPC(); outs << " NPC = " << thread->readNextNPC(); - newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); + newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); + //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); if(newVal != ccr) { outs << " CCR = " << newVal; ccr = newVal; } - newVal = thread->readMiscReg(SparcISA::MISCREG_Y); + newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1); + //newVal = thread->readMiscReg(SparcISA::MISCREG_Y); if(newVal != y) { outs << " Y = " << newVal; @@ -363,9 +365,13 @@ Trace::InstRecord::dump(ostream &outs) diffHtba = true; if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE)) diffPstate = true; - if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + //if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + if(shared_data->y != + thread->readIntReg(NumIntArchRegs + 1)) diffY = true; - if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + if(shared_data->ccr != + thread->readIntReg(NumIntArchRegs + 2)) diffCcr = true; if(shared_data->gl != thread->readMiscReg(MISCREG_GL)) diffGl = true; @@ -375,14 +381,22 @@ Trace::InstRecord::dump(ostream &outs) diffPil = true; if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP)) diffCwp = true; - if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + if(shared_data->cansave != + thread->readIntReg(NumIntArchRegs + 3)) diffCansave = true; + //if(shared_data->canrestore != + // thread->readMiscReg(MISCREG_CANRESTORE)) if(shared_data->canrestore != - thread->readMiscReg(MISCREG_CANRESTORE)) + thread->readMiscReg(NumIntArchRegs + 4)) diffCanrestore = true; - if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + if(shared_data->otherwin != + thread->readIntReg(NumIntArchRegs + 5)) diffOtherwin = true; - if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + if(shared_data->cleanwin != + thread->readMiscReg(NumIntArchRegs + 6)) diffCleanwin = true; if (diffPC || diffInst || diffRegs || diffTpc || diffTnpc || @@ -473,10 +487,12 @@ Trace::InstRecord::dump(ostream &outs) thread->readMiscReg(MISCREG_PSTATE), shared_data->pstate); printRegPair(outs, "Y", - thread->readMiscReg(MISCREG_Y), + //thread->readMiscReg(MISCREG_Y), + thread->readMiscReg(NumIntArchRegs + 1), shared_data->y); printRegPair(outs, "Ccr", - thread->readMiscReg(MISCREG_CCR), + //thread->readMiscReg(MISCREG_CCR), + thread->readMiscReg(NumIntArchRegs + 2), shared_data->ccr); printRegPair(outs, "Tl", thread->readMiscReg(MISCREG_TL), @@ -494,16 +510,20 @@ Trace::InstRecord::dump(ostream &outs) thread->readMiscReg(MISCREG_CWP), shared_data->cwp); printRegPair(outs, "Cansave", - thread->readMiscReg(MISCREG_CANSAVE), + //thread->readMiscReg(MISCREG_CANSAVE), + thread->readIntReg(NumIntArchRegs + 3), shared_data->cansave); printRegPair(outs, "Canrestore", - thread->readMiscReg(MISCREG_CANRESTORE), + //thread->readMiscReg(MISCREG_CANRESTORE), + thread->readIntReg(NumIntArchRegs + 4), shared_data->canrestore); printRegPair(outs, "Otherwin", - thread->readMiscReg(MISCREG_OTHERWIN), + //thread->readMiscReg(MISCREG_OTHERWIN), + thread->readIntReg(NumIntArchRegs + 5), shared_data->otherwin); printRegPair(outs, "Cleanwin", - thread->readMiscReg(MISCREG_CLEANWIN), + //thread->readMiscReg(MISCREG_CLEANWIN), + thread->readIntReg(NumIntArchRegs + 6), shared_data->cleanwin); outs << endl; for (int i = 1; i <= MaxTL; i++) { From 6aa06a26b7e0c1e44427aa5360cba5662f2907c9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:10:04 -0500 Subject: [PATCH 30/41] Changes to the isa_parser and affected files to fix an indexing problem with split execute instructions and miscregs aliasing with integer registers. src/arch/isa_parser.py: Rearranged things so that classes with more than one execute function treat operands properly. 1. Eliminated the CodeBlock class 2. Created a SubOperandList 3. Redefined how InstObjParams is constructed To define an InstObjParam, you can either pass in a single code literal which will be named "code", or you can pass in a dictionary of code snippets which will be substituted into the Templates. In order to get this to work, there is a new restriction that each template has only one function in it. These changes should only affect memory instructions which have regular and split execute functions. Also changed the MiscRegs so that they use the instrunctions srcReg and destReg arrays. src/arch/sparc/isa/formats/basic.isa: src/arch/sparc/isa/formats/branch.isa: src/arch/sparc/isa/formats/integerop.isa: src/arch/sparc/isa/formats/mem/basicmem.isa: src/arch/sparc/isa/formats/mem/blockmem.isa: src/arch/sparc/isa/formats/mem/util.isa: src/arch/sparc/isa/formats/nop.isa: src/arch/sparc/isa/formats/priv.isa: src/arch/sparc/isa/formats/trap.isa: Rearranged to work with new InstObjParam scheme. src/cpu/o3/sparc/dyn_inst.hh: Added functions to access the miscregs using the indexes from instructions srcReg and destReg arrays. Also changed the names of the other accessors so that they have the suffix "Operand" if they use those arrays. src/cpu/simple/base.hh: Added functions to access the miscregs using the indexes from instructions srcReg and destReg arrays. --HG-- extra : convert_revision : c91e1073138b72bcf4113a721e0ed40ec600cf2e --- src/arch/isa_parser.py | 221 ++++++++++++-------- src/arch/sparc/isa/formats/basic.isa | 3 +- src/arch/sparc/isa/formats/branch.isa | 6 +- src/arch/sparc/isa/formats/integerop.isa | 9 +- src/arch/sparc/isa/formats/mem/basicmem.isa | 25 ++- src/arch/sparc/isa/formats/mem/blockmem.isa | 48 ++--- src/arch/sparc/isa/formats/mem/util.isa | 43 ++-- src/arch/sparc/isa/formats/nop.isa | 4 +- src/arch/sparc/isa/formats/priv.isa | 8 +- src/arch/sparc/isa/formats/trap.isa | 4 +- src/cpu/o3/sparc/dyn_inst.hh | 70 +++++-- src/cpu/simple/base.hh | 25 +++ 12 files changed, 294 insertions(+), 172 deletions(-) diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index a96622d4a..aacdf455f 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -808,8 +808,7 @@ class GenCode: # a defineInst() method that generates the code for an instruction # definition. -exportContextSymbols = ('InstObjParams', 'CodeBlock', - 'makeList', 're', 'string') +exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string') exportContext = {} @@ -1003,27 +1002,83 @@ def substBitOps(code): # Template objects are format strings that allow substitution from # the attribute spaces of other objects (e.g. InstObjParams instances). +labelRE = re.compile(r'[^%]%\(([^\)]+)\)[sd]') + class Template: def __init__(self, t): self.template = t def subst(self, d): - # Start with the template namespace. Make a copy since we're - # going to modify it. - myDict = templateMap.copy() - # if the argument is a dictionary, we just use it. - if isinstance(d, dict): - myDict.update(d) - # if the argument is an object, we use its attribute map. - elif hasattr(d, '__dict__'): - myDict.update(d.__dict__) - else: - raise TypeError, "Template.subst() arg must be or have dictionary" + myDict = None + # Protect non-Python-dict substitutions (e.g. if there's a printf # in the templated C++ code) template = protect_non_subst_percents(self.template) # CPU-model-specific substitutions are handled later (in GenCode). template = protect_cpu_symbols(template) + + # if we're dealing with an InstObjParams object, we need to be a + # little more sophisticated. Otherwise, just do what we've always + # done + if isinstance(d, InstObjParams): + # The instruction wide parameters are already formed, but the + # parameters which are only function wide still need to be + # generated. + perFuncNames = ['op_decl', 'op_src_decl', 'op_dest_decl', \ + 'op_rd', 'op_wb', 'mem_acc_size', 'mem_acc_type'] + compositeCode = '' + + myDict = templateMap.copy() + myDict.update(d.__dict__) + # The "operands" and "snippets" attributes of the InstObjParams + # objects are for internal use and not substitution. + del myDict['operands'] + del myDict['snippets'] + + for name in labelRE.findall(template): + # Don't try to find a snippet to go with things that will + # match against attributes of d, or that are other templates, + # or that we're going to generate later, or that we've already + # found. + if not hasattr(d, name) and \ + not templateMap.has_key(name) and \ + not myDict.has_key(name) and \ + name not in perFuncNames: + myDict[name] = d.snippets[name] + if isinstance(myDict[name], str): + myDict[name] = substMungedOpNames(substBitOps(myDict[name])) + compositeCode += (" " + myDict[name]) + operands = SubOperandList(compositeCode, d.operands) + + myDict['op_decl'] = operands.concatAttrStrings('op_decl') + + is_src = lambda op: op.is_src + is_dest = lambda op: op.is_dest + + myDict['op_src_decl'] = \ + operands.concatSomeAttrStrings(is_src, 'op_src_decl') + myDict['op_dest_decl'] = \ + operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') + + myDict['op_rd'] = operands.concatAttrStrings('op_rd') + myDict['op_wb'] = operands.concatAttrStrings('op_wb') + + if d.operands.memOperand: + myDict['mem_acc_size'] = d.operands.memOperand.mem_acc_size + myDict['mem_acc_type'] = d.operands.memOperand.mem_acc_type + + else: + # Start with the template namespace. Make a copy since we're + # going to modify it. + myDict = templateMap.copy() + # if the argument is a dictionary, we just use it. + if isinstance(d, dict): + myDict.update(d) + # if the argument is an object, we use its attribute map. + elif hasattr(d, '__dict__'): + myDict.update(d.__dict__) + else: + raise TypeError, "Template.subst() arg must be or have dictionary" return template % myDict # Convert to string. This handles the case when a template with a @@ -1296,10 +1351,10 @@ class ControlRegOperand(Operand): def makeConstructor(self): c = '' if self.is_src: - c += '\n\t_srcRegIdx[%d] = %s;' % \ + c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \ (self.src_reg_idx, self.reg_spec) if self.is_dest: - c += '\n\t_destRegIdx[%d] = %s;' % \ + c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \ (self.dest_reg_idx, self.reg_spec) return c @@ -1307,7 +1362,7 @@ class ControlRegOperand(Operand): bit_select = 0 if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read control register as FP') - base = 'xc->readMiscReg(%s)' % self.reg_spec + base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx if self.size == self.dflt_size: return '%s = %s;\n' % (self.base_name, base) else: @@ -1317,7 +1372,8 @@ class ControlRegOperand(Operand): def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->setMiscRegWithEffect(%s, %s);\n' % (self.reg_spec, self.base_name) + wb = 'xc->setMiscRegOperandWithEffect(this, %s, %s);\n' % \ + (self.dest_reg_idx, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ self.base_name return wb @@ -1550,6 +1606,48 @@ class OperandList: def sort(self): self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) +class SubOperandList(OperandList): + + # Find all the operands in the given code block. Returns an operand + # descriptor list (instance of class OperandList). + def __init__(self, code, master_list): + self.items = [] + self.bases = {} + # delete comments so we don't match on reg specifiers inside + code = commentRE.sub('', code) + # search for operands + next_pos = 0 + while 1: + match = operandsRE.search(code, next_pos) + if not match: + # no more matches: we're done + break + op = match.groups() + # regexp groups are operand full name, base, and extension + (op_full, op_base, op_ext) = op + # find this op in the master list + op_desc = master_list.find_base(op_base) + if not op_desc: + error(0, 'Found operand %s which is not in the master list!' \ + ' This is an internal error' % \ + op_base) + else: + # See if we've already found this operand + op_desc = self.find_base(op_base) + if not op_desc: + # if not, add a reference to it to this sub list + self.append(master_list.bases[op_base]) + + # start next search after end of current match + next_pos = match.end() + self.sort() + self.memOperand = None + for op_desc in self.items: + if op_desc.isMem(): + if self.memOperand: + error(0, "Code block has more than one memory operand.") + self.memOperand = op_desc + # Regular expression object to match C++ comments # (used in findOperands()) commentRE = re.compile(r'//.*\n') @@ -1583,11 +1681,28 @@ def makeFlagConstructor(flag_list): code = pre + string.join(flag_list, post + pre) + post return code -class CodeBlock: - def __init__(self, code): - self.orig_code = code - self.operands = OperandList(code) - self.code = substMungedOpNames(substBitOps(code)) +# Assume all instruction flags are of the form 'IsFoo' +instFlagRE = re.compile(r'Is.*') + +# OpClass constants end in 'Op' except No_OpClass +opClassRE = re.compile(r'.*Op|No_OpClass') + +class InstObjParams: + def __init__(self, mnem, class_name, base_class = '', + snippets = None, opt_args = []): + self.mnemonic = mnem + self.class_name = class_name + self.base_class = base_class + compositeCode = '' + if snippets: + if not isinstance(snippets, dict): + snippets = {'code' : snippets} + for snippet in snippets.values(): + if isinstance(snippet, str): + compositeCode += (" " + snippet) + self.snippets = snippets + + self.operands = OperandList(compositeCode) self.constructor = self.operands.concatAttrStrings('constructor') self.constructor += \ '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs @@ -1597,28 +1712,10 @@ class CodeBlock: '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs self.constructor += \ '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs - - self.op_decl = self.operands.concatAttrStrings('op_decl') - - is_src = lambda op: op.is_src - is_dest = lambda op: op.is_dest - - self.op_src_decl = \ - self.operands.concatSomeAttrStrings(is_src, 'op_src_decl') - self.op_dest_decl = \ - self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') - - self.op_rd = self.operands.concatAttrStrings('op_rd') - self.op_wb = self.operands.concatAttrStrings('op_wb') - self.flags = self.operands.concatAttrLists('flags') - if self.operands.memOperand: - self.mem_acc_size = self.operands.memOperand.mem_acc_size - self.mem_acc_type = self.operands.memOperand.mem_acc_type - # Make a basic guess on the operand class (function unit type). - # These are good enough for most cases, and will be overridden + # These are good enough for most cases, and can be overridden # later otherwise. if 'IsStore' in self.flags: self.op_class = 'MemWriteOp' @@ -1629,48 +1726,6 @@ class CodeBlock: else: self.op_class = 'IntAluOp' -# Assume all instruction flags are of the form 'IsFoo' -instFlagRE = re.compile(r'Is.*') - -# OpClass constants end in 'Op' except No_OpClass -opClassRE = re.compile(r'.*Op|No_OpClass') - -class InstObjParams: - def __init__(self, mnem, class_name, base_class = '', - code = None, opt_args = [], extras = {}): - self.mnemonic = mnem - self.class_name = class_name - self.base_class = base_class - if code: - #If the user already made a CodeBlock, pick the parts from it - if isinstance(code, CodeBlock): - origCode = code.orig_code - codeBlock = code - else: - origCode = code - codeBlock = CodeBlock(code) - stringExtras = {} - otherExtras = {} - for (k, v) in extras.items(): - if type(v) == str: - stringExtras[k] = v - else: - otherExtras[k] = v - compositeCode = "\n".join([origCode] + stringExtras.values()) - # compositeCode = '\n'.join([origCode] + - # [pair[1] for pair in extras]) - compositeBlock = CodeBlock(compositeCode) - for code_attr in compositeBlock.__dict__.keys(): - setattr(self, code_attr, getattr(compositeBlock, code_attr)) - for (key, snippet) in stringExtras.items(): - setattr(self, key, CodeBlock(snippet).code) - for (key, item) in otherExtras.items(): - setattr(self, key, item) - self.code = codeBlock.code - self.orig_code = origCode - else: - self.constructor = '' - self.flags = [] # Optional arguments are assumed to be either StaticInst flags # or an OpClass value. To avoid having to import a complete # list of these values to match against, we do it ad-hoc diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index a4c05387b..56e933763 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -95,8 +95,7 @@ def template BasicDecodeWithMnemonic {{ // The most basic instruction format... used only for a few misc. insts def format BasicOperate(code, *flags) {{ - iop = InstObjParams(name, Name, 'SparcStaticInst', - CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 3062f38b2..2db756320 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -248,7 +248,6 @@ def format Branch(code, *opt_flags) {{ // Primary format for branch instructions: def format BranchN(bits, code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) new_opt_flags = [] for flag in opt_flags: if flag == ',a': @@ -256,7 +255,7 @@ def format BranchN(bits, code, *opt_flags) {{ Name += 'Annul' else: new_opt_flags += flag - iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, new_opt_flags) + iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, code, new_opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BranchExecute.subst(iop) @@ -266,8 +265,7 @@ def format BranchN(bits, code, *opt_flags) {{ // Primary format for branch instructions: def format BranchSplit(code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags) + iop = InstObjParams(name, Name, 'BranchSplit', code, 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 4f8ebebcc..363aca1a1 100644 --- a/src/arch/sparc/isa/formats/integerop.isa +++ b/src/arch/sparc/isa/formats/integerop.isa @@ -263,14 +263,15 @@ let {{ def doIntFormat(code, ccCode, name, Name, opt_flags): (usesImm, code, immCode, rString, iString) = splitOutImm(code) - iop = InstObjParams(name, Name, 'IntOp', code, - opt_flags, {"cc_code": ccCode}) + iop = InstObjParams(name, Name, 'IntOp', + {"code": code, "cc_code": ccCode}, + opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = IntOpExecute.subst(iop) if usesImm: imm_iop = InstObjParams(name, Name + 'Imm', 'IntOpImm' + iString, - immCode, opt_flags, {"cc_code": ccCode}) + {"code": immCode, "cc_code": ccCode}, opt_flags) header_output += BasicDeclare.subst(imm_iop) decoder_output += BasicConstructor.subst(imm_iop) exec_output += IntOpExecute.subst(imm_iop) @@ -341,7 +342,7 @@ def format IntOpCcRes(code, *opt_flags) {{ def format SetHi(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'SetHi', - code, opt_flags, {"cc_code": ''}) + {"code": code, "cc_code": ''}, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = IntOpExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index cb6c2f161..d5b17d720 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -55,15 +55,20 @@ let {{ def doMemFormat(code, execute, faultCode, name, Name, opt_flags): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' - iop = InstObjParams(name, Name, 'Mem', code, - opt_flags, {"fault_check": faultCode, "ea_code": addrCalcReg}) - iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', code, - opt_flags, {"fault_check": faultCode, "ea_code": addrCalcImm}) + iop = InstObjParams(name, Name, 'Mem', + {"code": code, "fault_check": faultCode, + "ea_code": addrCalcReg}, + opt_flags) + iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', + {"code": code, "fault_check": faultCode, + "ea_code": addrCalcImm}, + opt_flags) header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) - exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, execute, - faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags) + exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, + execute, faultCode, name, name + "Imm", + Name, Name + "Imm", opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; @@ -71,7 +76,7 @@ def format LoadAlt(code, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, LoadExecute, + decode_block) = doMemFormat(code, LoadFuncs, AlternateAsiPrivFaultCheck, name, Name, opt_flags) }}; @@ -79,7 +84,7 @@ def format StoreAlt(code, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, StoreExecute, + decode_block) = doMemFormat(code, StoreFuncs, AlternateAsiPrivFaultCheck, name, Name, opt_flags) }}; @@ -88,7 +93,7 @@ def format Load(code, *opt_flags) {{ decoder_output, exec_output, decode_block) = doMemFormat(code, - LoadExecute, '', name, Name, opt_flags) + LoadFuncs, '', name, Name, opt_flags) }}; def format Store(code, *opt_flags) {{ @@ -96,5 +101,5 @@ def format Store(code, *opt_flags) {{ decoder_output, exec_output, decode_block) = doMemFormat(code, - StoreExecute, '', name, Name, opt_flags) + StoreFuncs, '', name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index 8b4aca473..c124dc600 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -293,14 +293,14 @@ let {{ else: flag_code = "flags[IsDelayedCommit] = true;" pcedCode = matcher.sub("Frd_%d" % microPc, code) - iop = InstObjParams(name, Name, 'BlockMem', pcedCode, - opt_flags, {"ea_code": addrCalcReg, + iop = InstObjParams(name, Name, 'BlockMem', + {"code": pcedCode, "ea_code": addrCalcReg, "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}) - iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, - opt_flags, {"ea_code": addrCalcImm, + "set_flags": flag_code}, opt_flags) + iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', + {"code": pcedCode, "ea_code": addrCalcImm, "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}) + "set_flags": flag_code}, opt_flags) decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) exec_output += doDualSplitExecute( @@ -315,25 +315,25 @@ let {{ }}; def format BlockLoad(code, *opt_flags) {{ - # We need to make sure to check the highest priority fault last. - # That way, if other faults have been detected, they'll be overwritten - # rather than the other way around. - faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck - (header_output, - decoder_output, - exec_output, - decode_block) = doBlockMemFormat(code, faultCode, - LoadExecute, name, Name, opt_flags) + # We need to make sure to check the highest priority fault last. + # That way, if other faults have been detected, they'll be overwritten + # rather than the other way around. + faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck + (header_output, + decoder_output, + exec_output, + decode_block) = doBlockMemFormat(code, faultCode, + LoadFuncs, name, Name, opt_flags) }}; def format BlockStore(code, *opt_flags) {{ - # We need to make sure to check the highest priority fault last. - # That way, if other faults have been detected, they'll be overwritten - # rather than the other way around. - faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck - (header_output, - decoder_output, - exec_output, - decode_block) = doBlockMemFormat(code, faultCode, - StoreExecute, name, Name, opt_flags) + # We need to make sure to check the highest priority fault last. + # That way, if other faults have been detected, they'll be overwritten + # rather than the other way around. + faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck + (header_output, + decoder_output, + exec_output, + decode_block) = doBlockMemFormat(code, faultCode, + StoreFuncs, name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index f3adbe19f..e87223000 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -162,15 +162,17 @@ def template LoadExecute {{ return fault; } +}}; +def template LoadInitiateAcc {{ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; Addr EA; uint%(mem_acc_size)s_t Mem; - %(ea_decl)s; - %(ea_rd)s; + %(op_decl)s; + %(op_rd)s; %(ea_code)s; DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; @@ -180,18 +182,20 @@ def template LoadExecute {{ } return fault; } +}}; +def template LoadCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; - %(code_decl)s; - %(code_rd)s; + %(op_decl)s; + %(op_rd)s; Mem = pkt->get(); %(code)s; if(fault == NoFault) { - %(code_wb)s; + %(op_wb)s; } return fault; } @@ -228,7 +232,9 @@ def template StoreExecute {{ return fault; } +}}; +def template StoreInitiateAcc {{ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { @@ -255,7 +261,9 @@ def template StoreExecute {{ } return fault; } +}}; +def template StoreCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { @@ -275,6 +283,8 @@ def template CompleteAccDeclare {{ //Here are some code snippets which check for various fault conditions let {{ + LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc] + StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc] # The LSB can be zero, since it's really the MSB in doubles and quads # and we're dealing with doubles BlockAlignmentFaultCheck = ''' @@ -308,20 +318,10 @@ let {{ //and in the other they're distributed across two. Also note that for //execute functions, the name of the base class doesn't matter. let {{ - def doSplitExecute(code, execute, name, Name, opt_flags, microParam): - codeParam = microParam.copy() - codeParam["ea_code"] = '' - codeIop = InstObjParams(name, Name, '', code, opt_flags, codeParam) - eaIop = InstObjParams(name, Name, '', microParam["ea_code"], - opt_flags, microParam) - iop = InstObjParams(name, Name, '', code, opt_flags, microParam) - (iop.ea_decl, - iop.ea_rd, - iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb) - (iop.code_decl, - iop.code_rd, - iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb) - return execute.subst(iop) + def doSplitExecute(execute, name, Name, opt_flags, microParam): + iop = InstObjParams(name, Name, '', microParam, opt_flags) + (execf, initf, compf) = execute + return execf.subst(iop) + initf.subst(iop) + compf.subst(iop) def doDualSplitExecute(code, eaRegCode, eaImmCode, execute, @@ -330,8 +330,9 @@ let {{ for (eaCode, name, Name) in ( (eaRegCode, nameReg, NameReg), (eaImmCode, nameImm, NameImm)): - microParams = {"ea_code" : eaCode, "fault_check": faultCode} - executeCode += doSplitExecute(code, execute, name, Name, + microParams = {"code": code, "ea_code": eaCode, + "fault_check": faultCode} + executeCode += doSplitExecute(execute, name, Name, opt_flags, microParams) return executeCode }}; diff --git a/src/arch/sparc/isa/formats/nop.isa b/src/arch/sparc/isa/formats/nop.isa index 37ef2e8d0..de2ba2f54 100644 --- a/src/arch/sparc/isa/formats/nop.isa +++ b/src/arch/sparc/isa/formats/nop.isa @@ -88,9 +88,7 @@ def template NopExecute {{ // Primary format for integer operate instructions: def format Nop(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Nop', cblk, opt_flags) + iop = InstObjParams(name, Name, 'Nop', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 3d47ca02f..36403afb4 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -235,8 +235,9 @@ let {{ name = mnem regBase = 'WrPriv' break - iop = InstObjParams(name, Name, regBase, code, - opt_flags, {"check": checkCode, "reg_name": regName}) + iop = InstObjParams(name, Name, regBase, + {"code": code, "check": checkCode, "reg_name": regName}, + opt_flags) header_output = BasicDeclare.subst(iop) if regName == '': decoder_output = BasicConstructor.subst(iop) @@ -245,7 +246,8 @@ let {{ exec_output = PrivExecute.subst(iop) if usesImm: imm_iop = InstObjParams(name, Name + 'Imm', regBase + 'Imm', - immCode, opt_flags, {"check": checkCode, "reg_name": regName}) + {"code": immCode, "check": checkCode, "reg_name": regName}, + opt_flags) header_output += BasicDeclare.subst(imm_iop) if regName == '': decoder_output += BasicConstructor.subst(imm_iop) diff --git a/src/arch/sparc/isa/formats/trap.isa b/src/arch/sparc/isa/formats/trap.isa index 04d467cfe..9c118b227 100644 --- a/src/arch/sparc/isa/formats/trap.isa +++ b/src/arch/sparc/isa/formats/trap.isa @@ -83,9 +83,7 @@ def template TrapExecute {{ }}; def format Trap(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Trap', cblk, opt_flags) + iop = InstObjParams(name, Name, 'Trap', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index 2d73ca8d1..fda99cb6c 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -106,6 +106,45 @@ class SparcDynInst : public BaseDynInst this->threadNumber); } + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readMiscReg( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + { + return this->cpu->readMiscRegWithEffect( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Sets a misc. register. */ + void setMiscRegOperand(const StaticInst * si, + int idx, const TheISA::MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscReg( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + void setMiscRegOperandWithEffect( + const StaticInst *si, int idx, const TheISA::MiscReg &val) + { + return this->cpu->setMiscRegWithEffect( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + #if FULL_SYSTEM /** Calls hardware return from error interrupt. */ Fault hwrei(); @@ -130,30 +169,31 @@ class SparcDynInst : public BaseDynInst // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntReg(const StaticInst *si, int idx) + uint64_t readIntRegOperand(const StaticInst *si, int idx) { uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]); DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val); return this->cpu->readIntReg(this->_srcRegIdx[idx]); } - TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width) + TheISA::FloatReg readFloatRegOperand(const StaticInst *si, + int idx, int width) { return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } - TheISA::FloatReg readFloatReg(const StaticInst *si, int idx) + TheISA::FloatReg readFloatRegOperand(const StaticInst *si, int idx) { return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } - TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, + TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, int width) { return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } - TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx) + TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) { return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } @@ -161,38 +201,38 @@ class SparcDynInst : public BaseDynInst /** @todo: Make results into arrays so they can handle multiple dest * registers. */ - void setIntReg(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) { DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val); this->cpu->setIntReg(this->_destRegIdx[idx], val); - BaseDynInst::setIntReg(si, idx, val); + BaseDynInst::setIntRegOperand(si, idx, val); } - void setFloatReg(const StaticInst *si, int idx, + void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val, int width) { this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatReg(si, idx, val, width); + BaseDynInst::setFloatRegOperand(si, idx, val, width); } - void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val) + void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val) { this->cpu->setFloatReg(this->_destRegIdx[idx], val); - BaseDynInst::setFloatReg(si, idx, val); + BaseDynInst::setFloatRegOperand(si, idx, val); } - void setFloatRegBits(const StaticInst *si, int idx, + void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val, int width) { this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegBits(si, idx, val); + BaseDynInst::setFloatRegOperandBits(si, idx, val); } - void setFloatRegBits(const StaticInst *si, + void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val) { this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegBits(si, idx, val); + BaseDynInst::setFloatRegOperandBits(si, idx, val); } public: diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index c39bfa9cd..dd178f64d 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -303,6 +303,31 @@ class BaseSimpleCPU : public BaseCPU return thread->setMiscRegWithEffect(misc_reg, val); } + MiscReg readMiscRegOperand(const StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscReg(reg_idx); + } + + MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscRegWithEffect(reg_idx); + } + + void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscReg(reg_idx, val); + } + + void setMiscRegOperandWithEffect( + const StaticInst *si, int idx, const MiscReg &val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscRegWithEffect(reg_idx, val); + } + #if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } From 181f4f32f6a2ffd19700e54cd5581fce19ec04a5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:10:58 -0500 Subject: [PATCH 31/41] Made changes to CWP be non speculative. --HG-- extra : convert_revision : 43899bc97061c33e67a53179c23e46b079118117 --- src/arch/sparc/isa/operands.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 9a5fda6ff..256f2fa43 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -123,7 +123,7 @@ def operands {{ 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59), 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60), 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing']), 62), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 62), # 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), # 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), # 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), From 4d66ddbe35252d3d70a0c3d25d100672db5f1ef9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:22:19 -0500 Subject: [PATCH 32/41] Added a predicted NPC field, explicitly stored whether the instruction was predicted taken or not. --HG-- extra : convert_revision : ba668af302ca4d8a3a032e907d5058e1477f462a --- src/cpu/base_dyn_inst.hh | 47 ++++++++++++++++++++++++----------- src/cpu/base_dyn_inst_impl.hh | 6 +++-- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 17e121dbf..40e780695 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -221,6 +221,12 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Predicted next PC. */ Addr predPC; + /** Predicted next NPC. */ + Addr predNPC; + + /** If this is a branch that was predicted taken */ + bool predTaken; + /** Count of total number of dynamic instructions. */ static int instcount; @@ -336,10 +342,12 @@ class BaseDynInst : public FastAlloc, public RefCounted * @param inst The binary instruction. * @param PC The PC of the instruction. * @param pred_PC The predicted next PC. + * @param pred_NPC The predicted next NPC. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr pred_PC, + BaseDynInst(TheISA::ExtMachInst inst, Addr PC, + Addr pred_PC, Addr pred_NPC, InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. @@ -385,26 +393,35 @@ class BaseDynInst : public FastAlloc, public RefCounted Addr readNextNPC() { return nextNPC; } /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } + void setPredTarg(Addr predicted_PC, Addr predicted_NPC) + { + predPC = predicted_PC; + predNPC = predicted_NPC; + } - /** Returns the predicted target of the branch. */ - Addr readPredTarg() { return predPC; } + /** Returns the predicted PC immediately after the branch. */ + Addr readPredPC() { return predPC; } + + /** Returns the predicted PC two instructions after the branch */ + Addr readPredNPC() { return predNPC; } /** Returns whether the instruction was predicted taken or not. */ - bool predTaken() -#if ISA_HAS_DELAY_SLOT - { return predPC != (nextPC + sizeof(TheISA::MachInst)); } -#else - { return predPC != (PC + sizeof(TheISA::MachInst)); } -#endif + bool readPredTaken() + { + return predTaken; + } + + void setPredTaken(bool predicted_taken) + { + predTaken = predicted_taken; + } /** Returns whether the instruction mispredicted. */ bool mispredicted() -#if ISA_HAS_DELAY_SLOT - { return predPC != nextNPC; } -#else - { return predPC != nextPC; } -#endif + { + return predPC != nextPC || predNPC != nextNPC; + } + // // Instruction types. Forward checks to StaticInst object. // diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 2f6859de2..d47384871 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -63,8 +63,8 @@ my_hash_t thishash; template BaseDynInst::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, - Addr pred_PC, InstSeqNum seq_num, - ImplCPU *cpu) + Addr pred_PC, Addr pred_NPC, + InstSeqNum seq_num, ImplCPU *cpu) : staticInst(machInst), traceData(NULL), cpu(cpu) { seqNum = seq_num; @@ -73,6 +73,8 @@ BaseDynInst::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, nextPC = PC + sizeof(TheISA::MachInst); nextNPC = nextPC + sizeof(TheISA::MachInst); predPC = pred_PC; + predNPC = pred_NPC; + predTaken = false; initVars(); } From 37b9966eb466b1655f0d4e604bafa729a3aaea6a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:32:06 -0500 Subject: [PATCH 33/41] Made branch delay slots get squashed, and passed back an NPC and NNPC to start fetching from. --HG-- extra : convert_revision : a2e4845fedf113b5a2fd92d3d28ce5b006278103 --- src/cpu/o3/comm.hh | 3 ++ src/cpu/o3/commit_impl.hh | 2 + src/cpu/o3/cpu.cc | 2 +- src/cpu/o3/fetch.hh | 9 ++-- src/cpu/o3/fetch_impl.hh | 73 +++++++++++++++---------------- src/cpu/o3/iew_impl.hh | 24 +++++++--- src/cpu/o3/sparc/dyn_inst.hh | 4 +- src/cpu/o3/sparc/dyn_inst_impl.hh | 7 +-- 8 files changed, 70 insertions(+), 54 deletions(-) diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index 4683c77af..d96919007 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -90,6 +90,7 @@ struct DefaultIEWDefaultCommit { bool squashDelaySlot[Impl::MaxThreads]; uint64_t mispredPC[Impl::MaxThreads]; uint64_t nextPC[Impl::MaxThreads]; + uint64_t nextNPC[Impl::MaxThreads]; InstSeqNum squashedSeqNum[Impl::MaxThreads]; bool includeSquashInst[Impl::MaxThreads]; @@ -121,6 +122,7 @@ struct TimeBufStruct { bool branchTaken; uint64_t mispredPC; uint64_t nextPC; + uint64_t nextNPC; unsigned branchCount; }; @@ -160,6 +162,7 @@ struct TimeBufStruct { bool branchTaken; uint64_t mispredPC; uint64_t nextPC; + uint64_t nextNPC; // Represents the instruction that has either been retired or // squashed. Similar to having a single bus that broadcasts the diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 3178410a8..194138efc 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -514,6 +514,7 @@ DefaultCommit::squashAll(unsigned tid) toIEW->commitInfo[tid].branchMispredict = false; toIEW->commitInfo[tid].nextPC = PC[tid]; + toIEW->commitInfo[tid].nextNPC = nextPC[tid]; } template @@ -770,6 +771,7 @@ DefaultCommit::commit() fromIEW->branchTaken[tid]; toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid]; + toIEW->commitInfo[tid].nextNPC = fromIEW->nextNPC[tid]; toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid]; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 4056d876f..5616ba398 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -700,7 +700,7 @@ FullO3CPU::removeThread(unsigned tid) // Squash Throughout Pipeline InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; - fetch.squash(0, squash_seq_num, true, tid); + fetch.squash(0, sizeof(TheISA::MachInst), squash_seq_num, true, tid); decode.squash(tid); rename.squash(squash_seq_num, tid); iew.squash(tid); diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 04016347a..4f5a161e0 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -239,13 +239,13 @@ class DefaultFetch bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid); /** Squashes a specific thread and resets the PC. */ - inline void doSquash(const Addr &new_PC, unsigned tid); + inline void doSquash(const Addr &new_PC, const Addr &new_NPC, unsigned tid); /** Squashes a specific thread and resets the PC. Also tells the CPU to * remove any instructions between fetch and decode that should be sqaushed. */ - void squashFromDecode(const Addr &new_PC, const InstSeqNum &seq_num, - unsigned tid); + void squashFromDecode(const Addr &new_PC, const Addr &new_NPC, + const InstSeqNum &seq_num, unsigned tid); /** Checks if a thread is stalled. */ bool checkStall(unsigned tid) const; @@ -259,7 +259,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, const InstSeqNum &seq_num, + void squash(const Addr &new_PC, const Addr &new_NPC, + const InstSeqNum &seq_num, bool squash_delay_slot, unsigned tid); /** Ticks the fetch stage, processing all inputs signals and fetching diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 6cff52429..5cd2e3514 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -319,9 +319,7 @@ DefaultFetch::initStage() for (int tid = 0; tid < numThreads; tid++) { PC[tid] = cpu->readPC(tid); nextPC[tid] = cpu->readNextPC(tid); -#if ISA_HAS_DELAY_SLOT nextNPC[tid] = cpu->readNextNPC(tid); -#endif } // Size of cache block. @@ -504,14 +502,14 @@ DefaultFetch::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, if (!inst->isControl()) { #if ISA_HAS_DELAY_SLOT - 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); + next_PC = next_NPC; + next_NPC = next_NPC + instSize; + inst->setPredTarg(next_PC, next_NPC); #else next_PC = next_PC + instSize; - inst->setPredTarg(next_PC); + inst->setPredTarg(next_PC, next_PC + sizeof(TheISA::MachInst)); #endif + inst->setPredTaken(false); return false; } @@ -521,36 +519,29 @@ DefaultFetch::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, predict_taken = branchPred.predict(inst, pred_PC, tid); if (predict_taken) { - DPRINTF(Fetch, "[tid:%i]: Branch predicted to be true.\n", tid); + DPRINTF(Fetch, "[tid:%i]: Branch predicted to be taken.\n", tid); } else { - DPRINTF(Fetch, "[tid:%i]: Branch predicted to be false.\n", tid); + DPRINTF(Fetch, "[tid:%i]: Branch predicted to be not taken.\n", tid); } + next_PC = next_NPC; 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 - } - + } else { next_NPC = next_NPC + instSize; } #else predict_taken = branchPred.predict(inst, next_PC, tid); #endif + DPRINTF(Fetch, "[tid:%i]: Branch predicted to go to %#x and then %#x.\n", + tid, next_PC, next_NPC); + inst->setPredTarg(next_PC, next_NPC); + inst->setPredTaken(predict_taken); ++fetchedBranches; @@ -671,14 +662,15 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid template inline void -DefaultFetch::doSquash(const Addr &new_PC, unsigned tid) +DefaultFetch::doSquash(const Addr &new_PC, + const Addr &new_NPC, unsigned tid) { - DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x.\n", - tid, new_PC); + DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n", + tid, new_PC, new_NPC); PC[tid] = new_PC; - nextPC[tid] = new_PC + instSize; - nextNPC[tid] = new_PC + (2 * instSize); + nextPC[tid] = new_NPC; + nextNPC[tid] = new_NPC + instSize; // Clear the icache miss if it's outstanding. if (fetchStatus[tid] == IcacheWaitResponse) { @@ -704,13 +696,13 @@ DefaultFetch::doSquash(const Addr &new_PC, unsigned tid) template void -DefaultFetch::squashFromDecode(const Addr &new_PC, +DefaultFetch::squashFromDecode(const Addr &new_PC, const Addr &new_NPC, const InstSeqNum &seq_num, unsigned tid) { DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid); - doSquash(new_PC, tid); + doSquash(new_PC, new_NPC, tid); #if ISA_HAS_DELAY_SLOT if (seq_num <= delaySlotInfo[tid].branchSeqNum) { @@ -793,12 +785,13 @@ DefaultFetch::updateFetchStatus() template void -DefaultFetch::squash(const Addr &new_PC, const InstSeqNum &seq_num, +DefaultFetch::squash(const Addr &new_PC, const Addr &new_NPC, + const InstSeqNum &seq_num, bool squash_delay_slot, unsigned tid) { DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid); - doSquash(new_PC, tid); + doSquash(new_PC, new_NPC, tid); #if ISA_HAS_DELAY_SLOT if (seq_num <= delaySlotInfo[tid].branchSeqNum) { @@ -928,6 +921,7 @@ DefaultFetch::checkSignalsAndUpdate(unsigned tid) #endif // In any case, squash. squash(fromCommit->commitInfo[tid].nextPC, + fromCommit->commitInfo[tid].nextNPC, doneSeqNum, fromCommit->commitInfo[tid].squashDelaySlot, tid); @@ -985,6 +979,7 @@ DefaultFetch::checkSignalsAndUpdate(unsigned tid) #endif // Squash unless we're already squashing squashFromDecode(fromDecode->decodeInfo[tid].nextPC, + fromDecode->decodeInfo[tid].nextNPC, doneSeqNum, tid); @@ -1041,6 +1036,8 @@ DefaultFetch::fetch(bool &status_change) // The current PC. Addr &fetch_PC = PC[tid]; + Addr &fetch_NPC = nextPC[tid]; + // Fault code for memory access. Fault fault = NoFault; @@ -1097,7 +1094,8 @@ DefaultFetch::fetch(bool &status_change) } Addr next_PC = fetch_PC; - Addr next_NPC = next_PC + instSize; + Addr next_NPC = fetch_NPC; + InstSeqNum inst_seq; MachInst inst; ExtMachInst ext_inst; @@ -1144,8 +1142,9 @@ DefaultFetch::fetch(bool &status_change) #endif // Create a new DynInst from the instruction fetched. - DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, - next_PC, + DynInstPtr instruction = new DynInst(ext_inst, + fetch_PC, fetch_NPC, + next_PC, next_NPC, inst_seq, cpu); instruction->setTid(tid); @@ -1243,9 +1242,9 @@ DefaultFetch::fetch(bool &status_change) 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); + PC[tid] = next_PC; + nextPC[tid] = next_NPC; + nextNPC[tid] = next_NPC + instSize; delaySlotInfo[tid].targetReady = false; } else { diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 85db68576..24c8484b4 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -481,25 +481,28 @@ DefaultIEW::squashDueToBranch(DynInstPtr &inst, unsigned tid) toCommit->branchMispredict[tid] = true; #if ISA_HAS_DELAY_SLOT + int instSize = sizeof(TheISA::MachInst); bool branch_taken = - (inst->readNextNPC() != (inst->readPC() + 2 * sizeof(TheISA::MachInst)) && - inst->readNextNPC() != (inst->readPC() + 3 * sizeof(TheISA::MachInst))); + !(inst->readNextPC() + instSize == inst->readNextNPC() && + (inst->readNextPC() == inst->readPC() + instSize || + inst->readNextPC() == inst->readPC() + 2 * instSize)); DPRINTF(Sparc, "Branch taken = %s [sn:%i]\n", branch_taken ? "true": "false", inst->seqNum); toCommit->branchTaken[tid] = branch_taken; - bool squashDelaySlot = - (inst->readNextPC() != inst->readPC() + sizeof(TheISA::MachInst)); + bool squashDelaySlot = true; +// (inst->readNextPC() != inst->readPC() + sizeof(TheISA::MachInst)); DPRINTF(Sparc, "Squash delay slot = %s [sn:%i]\n", squashDelaySlot ? "true": "false", inst->seqNum); toCommit->squashDelaySlot[tid] = squashDelaySlot; //If we're squashing the delay slot, we need to pick back up at NextPC. //Otherwise, NextPC isn't being squashed, so we should pick back up at //NextNPC. - if (squashDelaySlot) + if (squashDelaySlot) { toCommit->nextPC[tid] = inst->readNextPC(); - else + toCommit->nextNPC[tid] = inst->readNextNPC(); + } else toCommit->nextPC[tid] = inst->readNextNPC(); #else toCommit->branchTaken[tid] = inst->readNextPC() != @@ -522,6 +525,9 @@ DefaultIEW::squashDueToMemOrder(DynInstPtr &inst, unsigned tid) toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->nextPC[tid] = inst->readNextPC(); +#if ISA_HAS_DELAY_SLOT + toCommit->nextNPC[tid] = inst->readNextNPC(); +#endif toCommit->includeSquashInst[tid] = false; @@ -538,6 +544,9 @@ DefaultIEW::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid) toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->nextPC[tid] = inst->readPC(); +#if ISA_HAS_DELAY_SLOT + toCommit->nextNPC[tid] = inst->readNextNPC(); +#endif // Must include the broadcasted SN in the squash. toCommit->includeSquashInst[tid] = true; @@ -1342,6 +1351,7 @@ DefaultIEW::executeInsts() fetchRedirect[tid] = true; DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); + DPRINTF(IEW, "Predicted target was %#x.\n", inst->predPC); #if ISA_HAS_DELAY_SLOT DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", inst->nextNPC); @@ -1352,7 +1362,7 @@ DefaultIEW::executeInsts() // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); - if (inst->predTaken()) { + if (inst->readPredTaken()) { predictedTakenIncorrect++; } else { predictedNotTakenIncorrect++; diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index fda99cb6c..e95ae2fd5 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -56,8 +56,8 @@ class SparcDynInst : public BaseDynInst public: /** BaseDynInst constructor given a binary instruction. */ - SparcDynInst(TheISA::ExtMachInst inst, Addr PC, - Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu); + SparcDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, + Addr Pred_PC, Addr Pred_NPC, InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ SparcDynInst(StaticInstPtr &_staticInst); diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh index b830ee7bd..c4d30b6f4 100644 --- a/src/cpu/o3/sparc/dyn_inst_impl.hh +++ b/src/cpu/o3/sparc/dyn_inst_impl.hh @@ -31,9 +31,10 @@ #include "cpu/o3/sparc/dyn_inst.hh" template -SparcDynInst::SparcDynInst(TheISA::ExtMachInst inst, Addr PC, - Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(inst, PC, Pred_PC, seq_num, cpu) +SparcDynInst::SparcDynInst(TheISA::ExtMachInst inst, + Addr PC, Addr NPC, Addr Pred_PC, Addr Pred_NPC, + InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst(inst, PC, NPC, Pred_PC, Pred_NPC, seq_num, cpu) { initVars(); } From 6413b74e4ff3ce879852162306dc18213f8562c5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:33:08 -0500 Subject: [PATCH 34/41] Make the decoder use the new setup in the dyninsts for branch prediction. --HG-- extra : convert_revision : 9a6d6c93e5b40a55774891df54d290ff557b322c --- src/cpu/o3/decode_impl.hh | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 80b6cc4c9..aea56cc27 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -741,7 +741,7 @@ DefaultDecode::decodeInsts(unsigned tid) // Ensure that if it was predicted as a branch, it really is a // branch. - if (inst->predTaken() && !inst->isControl()) { + if (inst->readPredTaken() && !inst->isControl()) { DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",inst->predPC, inst->nextPC + 4); @@ -760,26 +760,29 @@ DefaultDecode::decodeInsts(unsigned tid) if (inst->isDirectCtrl() && inst->isUncondCtrl()) { ++decodeBranchResolved; - if (inst->branchTarget() != inst->readPredTarg()) { + if (inst->branchTarget() != inst->readPredPC()) { ++decodeBranchMispred; // Might want to set some sort of boolean and just do // a check at the end #if !ISA_HAS_DELAY_SLOT squash(inst, inst->threadNumber); - inst->setPredTarg(inst->branchTarget()); + Addr target = inst->branchTarget(); + inst->setPredTarg(target, target + sizeof(TheISA::MachInst)); 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()) { + if (inst->readPredTaken() && 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()); + Addr target = inst->branchTarget(); + inst->setPredTarg(target, + target + sizeof(TheISA::MachInst)); break; } else { DPRINTF(Decode, "[tid:%i]: Misprediction detected at " @@ -798,7 +801,9 @@ DefaultDecode::decodeInsts(unsigned tid) if (squashAfterDelaySlot[tid]) { assert(!inst->isSquashed()); squash(squashInst[tid], squashInst[tid]->threadNumber); - squashInst[tid]->setPredTarg(squashInst[tid]->branchTarget()); + Addr target = squashInst[tid]->branchTarget(); + squashInst[tid]->setPredTarg(target, + target + sizeof(TheISA::MachInst)); assert(!inst->isSquashed()); break; } From 244506ae12d079e012ec40fe85b68f54d3fd91c6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:34:34 -0500 Subject: [PATCH 35/41] Make sure endian conversion is done on the memory data when it's just set to an existing buffer. --HG-- extra : convert_revision : 5a890091b6a31b5414acbf68f19e28d7122a98d7 --- src/cpu/o3/lsq_unit_impl.hh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 7ce3dc9cb..ebd9301f6 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -601,8 +601,17 @@ LSQUnit::writebackStores() TheISA::IntReg convertedData = TheISA::htog(storeQueue[storeWBIdx].data); - memcpy(inst->memData, (uint8_t *)&convertedData, - req->getSize()); + //FIXME This is a hack to get SPARC working. It, along with endianness + //in the memory system in general, need to be straightened out more + //formally. The problem is that the data's endianness is swapped when + //it's in the 64 bit data field in the store queue. The data that you + //want won't start at the beginning of the field anymore unless it was + //a 64 bit access. + memcpy(inst->memData, + (uint8_t *)&convertedData + + (TheISA::ByteOrderDiffers ? + (sizeof(TheISA::IntReg) - req->getSize()) : 0), + req->getSize()); PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); data_pkt->dataStatic(inst->memData); @@ -616,7 +625,7 @@ LSQUnit::writebackStores() DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " "to Addr:%#x, data:%#x [sn:%lli]\n", storeWBIdx, inst->readPC(), - req->getPaddr(), *(inst->memData), + req->getPaddr(), (int)*(inst->memData), inst->seqNum); // @todo: Remove this SC hack once the memory system handles it. From c6944e320cfa86d3f2ce628457aff4bc431e7189 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:35:56 -0500 Subject: [PATCH 36/41] Add in capability to return to unblocking after a squash. This is needed because if you don't squash -all- the instructions, you need to keep clearing out whatever is left in the skid buffer. --HG-- extra : convert_revision : 7308eda27f4366348cf5fce71ddfa4b217bc172d --- src/cpu/o3/rename.hh | 4 ++++ src/cpu/o3/rename_impl.hh | 44 ++++++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 1ede6f355..6b4628f92 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -415,6 +415,10 @@ class DefaultRename * after squashing. */ bool resumeSerialize; + /** Whether or not rename needs to resume clearing out the skidbuffer + * after squashing. */ + bool resumeUnblocking; + /** The number of threads active in rename. */ unsigned numThreads; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 0c211b183..7a7234965 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -44,6 +44,7 @@ DefaultRename::DefaultRename(Params *params) renameWidth(params->renameWidth), commitWidth(params->commitWidth), resumeSerialize(false), + resumeUnblocking(false), numThreads(params->numberOfThreads), maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs) { @@ -405,6 +406,9 @@ DefaultRename::squash(const InstSeqNum &squash_seq_num, unsigned tid) } slist_it++; } + resumeUnblocking = (skidBuffer[tid].size() != 0); + DPRINTF(Rename, "Resume unblocking set to %s\n", + resumeUnblocking ? "true" : "false"); #else skidBuffer[tid].clear(); #endif @@ -496,6 +500,12 @@ DefaultRename::rename(bool &status_change, unsigned tid) block(tid); toDecode->renameUnblock[tid] = false; } + } else if (renameStatus[tid] == Unblocking) { + if (resumeUnblocking) { + block(tid); + resumeUnblocking = false; + toDecode->renameUnblock[tid] = false; + } } if (renameStatus[tid] == Running || @@ -761,7 +771,17 @@ DefaultRename::skidInsert(unsigned tid) } if (skidBuffer[tid].size() > skidBufferMax) + { + typename InstQueue::iterator it; + warn("Skidbuffer contents:\n"); + for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++) + { + warn("[tid:%u]: %s [sn:%i].\n", tid, + (*it)->staticInst->disassemble(inst->readPC()), + (*it)->seqNum); + } panic("Skidbuffer Exceeded Max Size"); + } } template @@ -848,7 +868,10 @@ DefaultRename::block(unsigned tid) // Only signal backwards to block if the previous stages do not think // rename is already blocked. if (renameStatus[tid] != Blocked) { - if (renameStatus[tid] != Unblocking) { + // If resumeUnblocking is set, we unblocked during the squash, + // but now we're have unblocking status. We need to tell earlier + // stages to block. + if (resumeUnblocking || renameStatus[tid] != Unblocking) { toDecode->renameBlock[tid] = true; toDecode->renameUnblock[tid] = false; wroteToTimeBuffer = true; @@ -1264,18 +1287,23 @@ DefaultRename::checkSignalsAndUpdate(unsigned tid) if (renameStatus[tid] == Squashing) { // Switch status to running if rename isn't being told to block or // squash this cycle. - if (!resumeSerialize) { - DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", - tid); - - renameStatus[tid] = Running; - return false; - } else { + if (resumeSerialize) { DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n", tid); renameStatus[tid] = SerializeStall; return true; + } else if (resumeUnblocking) { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n", + tid); + renameStatus[tid] = Unblocking; + return true; + } else { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", + tid); + + renameStatus[tid] = Running; + return false; } } From 569e0e883bf1f2d068cc0591b59998d956a8669f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:37:33 -0500 Subject: [PATCH 37/41] Add in constants which let you explicitly check if endian conversion would do anything. This was needed for a case where a piece of data was within a larger data type. When the larger data type was swapped, the location of the smaller data type would move. --HG-- extra : convert_revision : 4c904c964678529c72b8f1044dfcb400604f6654 --- src/sim/byteswap.hh | 54 +++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh index 7b1ae701e..7b63cf6e0 100644 --- a/src/sim/byteswap.hh +++ b/src/sim/byteswap.hh @@ -57,6 +57,8 @@ #include #endif +enum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder}; + //These functions actually perform the swapping for parameters //of various bit lengths static inline uint64_t @@ -131,11 +133,13 @@ template static inline T letobe(T value) {return swap_byte(value);} //For conversions not involving the guest system, we can define the functions //conditionally based on the BYTE_ORDER macro and outside of the namespaces #if defined(_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN +const ByteOrder HostByteOrder = BigEndianByteOrder; template static inline T htole(T value) {return swap_byte(value);} template static inline T letoh(T value) {return swap_byte(value);} template static inline T htobe(T value) {return value;} template static inline T betoh(T value) {return value;} #elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN +const ByteOrder HostByteOrder = LittleEndianByteOrder; template static inline T htole(T value) {return value;} template static inline T letoh(T value) {return value;} template static inline T htobe(T value) {return swap_byte(value);} @@ -146,33 +150,35 @@ template static inline T betoh(T value) {return swap_byte(value);} namespace BigEndianGuest { - template - static inline T gtole(T value) {return betole(value);} - template - static inline T letog(T value) {return letobe(value);} - template - static inline T gtobe(T value) {return value;} - template - static inline T betog(T value) {return value;} - template - static inline T htog(T value) {return htobe(value);} - template - static inline T gtoh(T value) {return betoh(value);} + const bool ByteOrderDiffers = (HostByteOrder != BigEndianByteOrder); + template + static inline T gtole(T value) {return betole(value);} + template + static inline T letog(T value) {return letobe(value);} + template + static inline T gtobe(T value) {return value;} + template + static inline T betog(T value) {return value;} + template + static inline T htog(T value) {return htobe(value);} + template + static inline T gtoh(T value) {return betoh(value);} } namespace LittleEndianGuest { - template - static inline T gtole(T value) {return value;} - template - static inline T letog(T value) {return value;} - template - static inline T gtobe(T value) {return letobe(value);} - template - static inline T betog(T value) {return betole(value);} - template - static inline T htog(T value) {return htole(value);} - template - static inline T gtoh(T value) {return letoh(value);} + const bool ByteOrderDiffers = (HostByteOrder != LittleEndianByteOrder); + template + static inline T gtole(T value) {return value;} + template + static inline T letog(T value) {return value;} + template + static inline T gtobe(T value) {return letobe(value);} + template + static inline T betog(T value) {return betole(value);} + template + static inline T htog(T value) {return htole(value);} + template + static inline T gtoh(T value) {return letoh(value);} } #endif // __SIM_BYTE_SWAP_HH__ From f410d5f4e0348b4499f313fb3870a48183772c20 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:39:44 -0500 Subject: [PATCH 38/41] Don't have "predict" set the predicted target of the instruction. Do that explicitly when you use predict. --HG-- extra : convert_revision : 8b613bb365b31ffaef1cea9fd789abe46219bdcf --- src/cpu/o3/bpred_unit_impl.hh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index 477c8e4cb..dbc603082 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -233,15 +233,6 @@ BPredUnit::predict(DynInstPtr &inst, Addr &PC, unsigned tid) } } - if (pred_taken) { - // Set the PC and the instruction's predicted target. - PC = target; - inst->setPredTarg(target); - } else { - PC = PC + sizeof(MachInst); - inst->setPredTarg(PC); - } - predHist[tid].push_front(predict_record); DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size()); From a6eb16adb424bca1a1a1d13604def2f15c8624d1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 07:47:33 -0500 Subject: [PATCH 39/41] Accidently "cleaned" away the NPC parameter to the constructor. --HG-- extra : convert_revision : 46670ee86000dfb171d327eb8f58555a4afb2360 --- src/cpu/base_dyn_inst.hh | 2 +- src/cpu/base_dyn_inst_impl.hh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 40e780695..07d53d278 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -346,7 +346,7 @@ class BaseDynInst : public FastAlloc, public RefCounted * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(TheISA::ExtMachInst inst, Addr PC, + BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr pred_PC, Addr pred_NPC, InstSeqNum seq_num, ImplCPU *cpu); diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index d47384871..c3d71e428 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -62,7 +62,8 @@ my_hash_t thishash; #endif template -BaseDynInst::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, +BaseDynInst::BaseDynInst(TheISA::ExtMachInst machInst, + Addr inst_PC, Addr inst_NPC, Addr pred_PC, Addr pred_NPC, InstSeqNum seq_num, ImplCPU *cpu) : staticInst(machInst), traceData(NULL), cpu(cpu) @@ -70,7 +71,7 @@ BaseDynInst::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, seqNum = seq_num; PC = inst_PC; - nextPC = PC + sizeof(TheISA::MachInst); + nextPC = inst_NPC; nextNPC = nextPC + sizeof(TheISA::MachInst); predPC = pred_PC; predNPC = pred_NPC; From 96e5086c817bb465308588d0235d7f237e8d9c8f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 09:34:20 -0500 Subject: [PATCH 40/41] Make fetch detect when a branch is happening, rather than trying to compute when. --HG-- extra : convert_revision : 1a8edc004570abb48e6c4cdf1b43c5699866838e --- src/cpu/o3/fetch_impl.hh | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 5cd2e3514..815935db3 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1114,15 +1114,17 @@ DefaultFetch::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 || delaySlotInfo[tid].numInsts > 0); + !predicted_branch; ++numInst) { + // If we're branching after this instruction, quite fetching + // from the same block then. + predicted_branch = + (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC); + // Get a sequence number. inst_seq = cpu->getAndIncrementInstSeq(); @@ -1166,8 +1168,7 @@ DefaultFetch::fetch(bool &status_change) instruction->staticInst, instruction->readPC()); - predicted_branch = lookupAndUpdateNextPC(instruction, next_PC, - next_NPC); + lookupAndUpdateNextPC(instruction, next_PC, next_NPC); // Add instruction to the CPU's list of instructions. instruction->setInstListIt(cpu->addInst(instruction)); @@ -1183,6 +1184,7 @@ DefaultFetch::fetch(bool &status_change) // Move to the next instruction, unless we have a branch. fetch_PC = next_PC; + fetch_NPC = next_NPC; if (instruction->isQuiesce()) { DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!", @@ -1194,29 +1196,6 @@ DefaultFetch::fetch(bool &status_change) } offset += instSize; - -#if ISA_HAS_DELAY_SLOT - 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) { @@ -1225,7 +1204,7 @@ DefaultFetch::fetch(bool &status_change) } 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) { + } else if (predicted_branch) { DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch " "instruction encountered.\n", tid); } From f4f00c5ae98c069f79a8b56ed93284daf7532c7e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 16 Dec 2006 09:35:09 -0500 Subject: [PATCH 41/41] Switch the endianness of data that's forwarded. This is the same sort of problem that was happening when stores went all the way to memory and back. --HG-- extra : convert_revision : 09fece7ae934f542e51046d33505df3f7ec0b919 --- src/cpu/o3/lsq_unit.hh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index a2e11173e..0318175c3 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -561,6 +561,12 @@ LSQUnit::read(Request *req, T &data, int load_idx) // Cast this to type T? data = storeQueue[store_idx].data >> shift_amt; + // When the data comes from the store queue entry, it's in host + // order. When it gets sent to the load, it needs to be in guest + // order so when the load converts it again, it ends up back + // in host order like the inst expects. + data = TheISA::htog(data); + assert(!load_inst->memData); load_inst->memData = new uint8_t[64];