diff options
author | Yasuko Eckert <yasuko.eckert@amd.com> | 2013-10-15 14:22:44 -0400 |
---|---|---|
committer | Yasuko Eckert <yasuko.eckert@amd.com> | 2013-10-15 14:22:44 -0400 |
commit | 2c293823aa7cb6d2cac4c0ff35e2023ff132a8f2 (patch) | |
tree | 040fdd5bad814d7cb7ee40934974d2b38b28d67a | |
parent | 552622184752dc798bc81f9b0b395db68aee9511 (diff) | |
download | gem5-2c293823aa7cb6d2cac4c0ff35e2023ff132a8f2.tar.xz |
cpu: add a condition-code register class
Add a third register class for condition codes,
in parallel with the integer and FP classes.
No ISAs use the CC class at this point though.
57 files changed, 806 insertions, 36 deletions
diff --git a/src/arch/SConscript b/src/arch/SConscript index b4f94a65f..e7d74ce51 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -135,5 +135,6 @@ env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) DebugFlag('IntRegs') DebugFlag('FloatRegs') +DebugFlag('CCRegs') DebugFlag('MiscRegs') -CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'MiscRegs' ]) +CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'CCRegs', 'MiscRegs' ]) diff --git a/src/arch/alpha/isa.hh b/src/arch/alpha/isa.hh index e2e2daba8..d30499066 100644 --- a/src/arch/alpha/isa.hh +++ b/src/arch/alpha/isa.hh @@ -103,6 +103,13 @@ namespace AlphaISA return reg; } + // dummy + int + flattenCCIndex(int reg) + { + return reg; + } + const Params *params() const; ISA(Params *p); diff --git a/src/arch/alpha/registers.hh b/src/arch/alpha/registers.hh index 92ba22ee8..3fd774cf7 100644 --- a/src/arch/alpha/registers.hh +++ b/src/arch/alpha/registers.hh @@ -53,6 +53,9 @@ typedef uint64_t FloatRegBits; // control register file contents typedef uint64_t MiscReg; +// dummy typedef since we don't have CC regs +typedef uint8_t CCReg; + union AnyReg { IntReg intreg; @@ -91,6 +94,7 @@ const int NumFloatArchRegs = 32; const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; const int NumFloatRegs = NumFloatArchRegs; +const int NumCCRegs = 0; const int NumMiscRegs = NUM_MISCREGS; const int TotalNumRegs = @@ -101,7 +105,8 @@ enum DependenceTags { // 0..31 are the integer regs 0..31 // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Reg_Base) FP_Reg_Base = NumIntRegs, - Misc_Reg_Base = FP_Reg_Base + NumFloatRegs, + CC_Reg_Base = FP_Reg_Base + NumFloatRegs, + Misc_Reg_Base = CC_Reg_Base + NumCCRegs, // NumCCRegs == 0 Max_Reg_Index = Misc_Reg_Base + NumMiscRegs + NumInternalProcRegs }; diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 32fc0b141..2dfe00f96 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -71,6 +71,9 @@ copyRegs(ThreadContext *src, ThreadContext *dest) for (int i = 0; i < NumFloatRegs; ++i) dest->setFloatRegBits(i, src->readFloatRegBits(i)); + // Would need to add condition-code regs if implemented + assert(NumCCRegs == 0); + // Copy misc. registers copyMiscRegs(src, dest); diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 3ab7dfb0e..2a8dee162 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -239,6 +239,8 @@ ArmStaticInst::printReg(std::ostream &os, int reg) const assert(rel_reg < NUM_MISCREGS); ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]); break; + case CCRegClass: + panic("printReg: CCRegClass but ARM has no CC regs\n"); } } diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index e7abb26b2..6fd57549a 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -140,6 +140,13 @@ namespace ArmISA return reg; } + // dummy + int + flattenCCIndex(int reg) + { + return reg; + } + int flattenMiscIndex(int reg) { diff --git a/src/arch/arm/registers.hh b/src/arch/arm/registers.hh index cc4fac824..b9033fd5b 100644 --- a/src/arch/arm/registers.hh +++ b/src/arch/arm/registers.hh @@ -68,6 +68,9 @@ typedef float FloatReg; // cop-0/cop-1 system control register typedef uint64_t MiscReg; +// dummy typedef since we don't have CC regs +typedef uint8_t CCReg; + // Constants Related to the number of registers const int NumIntArchRegs = NUM_ARCH_INTREGS; // The number of single precision floating point registers @@ -76,6 +79,7 @@ const int NumFloatSpecialRegs = 8; const int NumIntRegs = NUM_INTREGS; const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs; +const int NumCCRegs = 0; const int NumMiscRegs = NUM_MISCREGS; const int TotalNumRegs = NumIntRegs + NumFloatRegs + NumMiscRegs; @@ -102,7 +106,8 @@ const int SyscallSuccessReg = ReturnValueReg; // These help enumerate all the registers for dependence tracking. const int FP_Reg_Base = NumIntRegs * (MODE_MAXMODE + 1); -const int Misc_Reg_Base = FP_Reg_Base + NumFloatRegs; +const int CC_Reg_Base = FP_Reg_Base + NumFloatRegs; +const int Misc_Reg_Base = CC_Reg_Base + NumCCRegs; // NumCCRegs == 0 const int Max_Reg_Index = Misc_Reg_Base + NumMiscRegs; typedef union { diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 776c1ae82..cddc2c5c4 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -113,7 +113,7 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) void skipFunction(ThreadContext *tc) { - TheISA::PCState newPC = tc->pcState(); + PCState newPC = tc->pcState(); newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1)); CheckerCPU *checker = tc->getCheckerCpuPtr(); @@ -127,13 +127,16 @@ skipFunction(ThreadContext *tc) void copyRegs(ThreadContext *src, ThreadContext *dest) { - for (int i = 0; i < TheISA::NumIntRegs; i++) + for (int i = 0; i < NumIntRegs; i++) dest->setIntRegFlat(i, src->readIntRegFlat(i)); - for (int i = 0; i < TheISA::NumFloatRegs; i++) + for (int i = 0; i < NumFloatRegs; i++) dest->setFloatRegFlat(i, src->readFloatRegFlat(i)); - for (int i = 0; i < TheISA::NumMiscRegs; i++) + // Would need to add condition-code regs if implemented + assert(NumCCRegs == 0); + + for (int i = 0; i < NumMiscRegs; i++) dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); // setMiscReg "with effect" will set the misc register mapping correctly. diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index e4f81c173..dd9f2e873 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -1,4 +1,5 @@ # Copyright (c) 2003-2005 The Regents of The University of Michigan +# Copyright (c) 2013 Advanced Micro Devices, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -497,6 +498,9 @@ class Operand(object): def isIntReg(self): return 0 + def isCCReg(self): + return 0 + def isControlReg(self): return 0 @@ -660,6 +664,79 @@ class FloatRegOperand(Operand): }''' % (self.ctype, self.base_name, wp) return wb +class CCRegOperand(Operand): + def isReg(self): + return 1 + + def isCCReg(self): + return 1 + + def makeConstructor(self, predRead, predWrite): + c_src = '' + c_dest = '' + + if self.is_src: + c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + CC_Reg_Base;' % \ + (self.reg_spec) + if self.hasReadPred(): + c_src = '\n\tif (%s) {%s\n\t}' % \ + (self.read_predicate, c_src) + + if self.is_dest: + c_dest = \ + '\n\t_destRegIdx[_numDestRegs++] = %s + CC_Reg_Base;' % \ + (self.reg_spec) + c_dest += '\n\t_numCCDestRegs++;' + if self.hasWritePred(): + c_dest = '\n\tif (%s) {%s\n\t}' % \ + (self.write_predicate, c_dest) + + return c_src + c_dest + + def makeRead(self, predRead): + if (self.ctype == 'float' or self.ctype == 'double'): + error('Attempt to read condition-code register as FP') + if self.read_code != None: + return self.buildReadCode('readCCRegOperand') + + int_reg_val = '' + if predRead: + int_reg_val = 'xc->readCCRegOperand(this, _sourceIndex++)' + if self.hasReadPred(): + int_reg_val = '(%s) ? %s : 0' % \ + (self.read_predicate, int_reg_val) + else: + int_reg_val = 'xc->readCCRegOperand(this, %d)' % self.src_reg_idx + + return '%s = %s;\n' % (self.base_name, int_reg_val) + + def makeWrite(self, predWrite): + if (self.ctype == 'float' or self.ctype == 'double'): + error('Attempt to write condition-code register as FP') + if self.write_code != None: + return self.buildWriteCode('setCCRegOperand') + + if predWrite: + wp = 'true' + if self.hasWritePred(): + wp = self.write_predicate + + wcond = 'if (%s)' % (wp) + windex = '_destIndex++' + else: + wcond = '' + windex = '%d' % self.dest_reg_idx + + wb = ''' + %s + { + %s final_val = %s; + xc->setCCRegOperand(this, %s, final_val);\n + if (traceData) { traceData->setData(final_val); } + }''' % (wcond, self.ctype, self.base_name, windex) + + return wb + class ControlRegOperand(Operand): def isReg(self): return 1 @@ -815,6 +892,7 @@ class OperandList(object): self.numDestRegs = 0 self.numFPDestRegs = 0 self.numIntDestRegs = 0 + self.numCCDestRegs = 0 self.numMiscDestRegs = 0 self.memOperand = None @@ -835,6 +913,8 @@ class OperandList(object): self.numFPDestRegs += 1 elif op_desc.isIntReg(): self.numIntDestRegs += 1 + elif op_desc.isCCReg(): + self.numCCDestRegs += 1 elif op_desc.isControlReg(): self.numMiscDestRegs += 1 elif op_desc.isMem(): @@ -1030,6 +1110,7 @@ class InstObjParams(object): header += '\n\t_numDestRegs = 0;' header += '\n\t_numFPDestRegs = 0;' header += '\n\t_numIntDestRegs = 0;' + header += '\n\t_numCCDestRegs = 0;' self.constructor = header + \ self.operands.concatAttrStrings('constructor') diff --git a/src/arch/mips/isa.hh b/src/arch/mips/isa.hh index 04d4a1dfa..c601cfc1e 100644 --- a/src/arch/mips/isa.hh +++ b/src/arch/mips/isa.hh @@ -177,6 +177,13 @@ namespace MipsISA { return reg; } + + // dummy + int + flattenCCIndex(int reg) + { + return reg; + } }; } diff --git a/src/arch/mips/registers.hh b/src/arch/mips/registers.hh index d9d94e47b..0ac84cc7f 100644 --- a/src/arch/mips/registers.hh +++ b/src/arch/mips/registers.hh @@ -54,6 +54,7 @@ const int NumFloatSpecialRegs = 5; const int MaxShadowRegSets = 16; // Maximum number of shadow register sets const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// +const int NumCCRegs = 0; const uint32_t MIPS32_QNAN = 0x7fbfffff; const uint64_t MIPS64_QNAN = ULL(0x7ff7ffffffffffff); @@ -276,7 +277,8 @@ const int NumMiscRegs = MISCREG_NUMREGS; // These help enumerate all the registers for dependence tracking. const int FP_Reg_Base = NumIntRegs; -const int Misc_Reg_Base = FP_Reg_Base + NumFloatRegs; +const int CC_Reg_Base = FP_Reg_Base + NumFloatRegs; +const int Misc_Reg_Base = CC_Reg_Base + NumCCRegs; // NumCCRegs == 0 const int Max_Reg_Index = Misc_Reg_Base + NumMiscRegs; const int TotalNumRegs = NumIntRegs + NumFloatRegs + NumMiscRegs; @@ -292,6 +294,9 @@ typedef float FloatReg; // cop-0/cop-1 system control register typedef uint64_t MiscReg; +// dummy typedef since we don't have CC regs +typedef uint8_t CCReg; + typedef union { IntReg intreg; FloatReg fpreg; diff --git a/src/arch/null/registers.hh b/src/arch/null/registers.hh index f33b7e5bd..1e52fc5a6 100644 --- a/src/arch/null/registers.hh +++ b/src/arch/null/registers.hh @@ -47,6 +47,7 @@ namespace NullISA { typedef uint64_t IntReg; typedef uint32_t FloatRegBits; typedef float FloatReg; +typedef uint8_t CCReg; typedef uint64_t MiscReg; } diff --git a/src/arch/power/insts/static_inst.cc b/src/arch/power/insts/static_inst.cc index 09b662453..087e1f740 100644 --- a/src/arch/power/insts/static_inst.cc +++ b/src/arch/power/insts/static_inst.cc @@ -55,6 +55,8 @@ PowerStaticInst::printReg(std::ostream &os, int reg) const default: ccprintf(os, "unknown_reg"); break; } + case CCRegClass: + panic("printReg: POWER does not implement CCRegClass\n"); } } diff --git a/src/arch/power/isa.hh b/src/arch/power/isa.hh index 33439c48c..7b59b2ad1 100644 --- a/src/arch/power/isa.hh +++ b/src/arch/power/isa.hh @@ -98,6 +98,13 @@ class ISA : public SimObject return reg; } + // dummy + int + flattenCCIndex(int reg) + { + return reg; + } + void startup(ThreadContext *tc) {} /// Explicitly import the otherwise hidden startup diff --git a/src/arch/power/registers.hh b/src/arch/power/registers.hh index 89de3719c..abee516fc 100644 --- a/src/arch/power/registers.hh +++ b/src/arch/power/registers.hh @@ -52,6 +52,9 @@ typedef uint64_t FloatRegBits; typedef double FloatReg; typedef uint64_t MiscReg; +// dummy typedef since we don't have CC regs +typedef uint8_t CCReg; + // Constants Related to the number of registers const int NumIntArchRegs = 32; @@ -64,6 +67,7 @@ const int NumInternalProcRegs = 0; const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs; +const int NumCCRegs = 0; const int NumMiscRegs = NUM_MISCREGS; // Semantically meaningful register indices @@ -85,7 +89,8 @@ const int SyscallSuccessReg = 3; // These help enumerate all the registers for dependence tracking. const int FP_Reg_Base = NumIntRegs; -const int Misc_Reg_Base = FP_Reg_Base + NumFloatRegs; +const int CC_Reg_Base = FP_Reg_Base + NumFloatRegs; +const int Misc_Reg_Base = CC_Reg_Base + NumCCRegs; // NumCCRegs == 0 const int Max_Reg_Index = Misc_Reg_Base + NumMiscRegs; typedef union { diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc index e3fa246fc..7be195b8d 100644 --- a/src/arch/power/utility.cc +++ b/src/arch/power/utility.cc @@ -48,6 +48,9 @@ copyRegs(ThreadContext *src, ThreadContext *dest) for (int i = 0; i < NumFloatRegs; ++i) dest->setFloatRegBits(i, src->readFloatRegBits(i)); + // Would need to add condition-code regs if implemented + assert(NumCCRegs == 0); + // Copy misc. registers copyMiscRegs(src, dest); diff --git a/src/arch/sparc/isa.hh b/src/arch/sparc/isa.hh index 86092f3b5..e6f023bc0 100644 --- a/src/arch/sparc/isa.hh +++ b/src/arch/sparc/isa.hh @@ -206,6 +206,13 @@ class ISA : public SimObject return reg; } + // dummy + int + flattenCCIndex(int reg) + { + return reg; + } + typedef SparcISAParams Params; const Params *params() const; diff --git a/src/arch/sparc/registers.hh b/src/arch/sparc/registers.hh index 0e774b69e..b25f34584 100644 --- a/src/arch/sparc/registers.hh +++ b/src/arch/sparc/registers.hh @@ -48,6 +48,10 @@ typedef uint64_t IntReg; typedef uint64_t MiscReg; typedef float FloatReg; typedef uint32_t FloatRegBits; + +// dummy typedef since we don't have CC regs +typedef uint8_t CCReg; + typedef union { IntReg intReg; @@ -70,14 +74,16 @@ const int SyscallPseudoReturnReg = 9; const int NumIntArchRegs = 32; const int NumIntRegs = (MaxGL + 1) * 8 + NWindows * 16 + NumMicroIntRegs; +const int NumCCRegs = 0; const int TotalNumRegs = NumIntRegs + NumFloatRegs + NumMiscRegs; // These enumerate all the registers for dependence tracking. enum DependenceTags { FP_Reg_Base = NumIntRegs, - Misc_Reg_Base = FP_Reg_Base + NumFloatRegs, - Max_Reg_Index = Misc_Reg_Base + NumMiscRegs + CC_Reg_Base = FP_Reg_Base + NumFloatRegs, + Misc_Reg_Base = CC_Reg_Base + NumCCRegs, // NumCCRegs == 0 + Max_Reg_Index = Misc_Reg_Base + NumMiscRegs, }; } // namespace SparcISA diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index d99ef4aa0..9fa102c6a 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -234,6 +234,9 @@ copyRegs(ThreadContext *src, ThreadContext *dest) dest->setFloatRegBits(i, src->readFloatRegBits(i)); } + // Would need to add condition-code regs if implemented + assert(NumCCRegs == 0); + // Copy misc. registers copyMiscRegs(src, dest); diff --git a/src/arch/x86/insts/static_inst.cc b/src/arch/x86/insts/static_inst.cc index 046a11fb6..39091289f 100644 --- a/src/arch/x86/insts/static_inst.cc +++ b/src/arch/x86/insts/static_inst.cc @@ -221,6 +221,10 @@ namespace X86ISA break; } + case CCRegClass: + ccprintf(os, "%%cc%d", rel_reg); + break; + case MiscRegClass: switch (rel_reg) { default: diff --git a/src/arch/x86/isa.hh b/src/arch/x86/isa.hh index 3ccc2f0ad..5f36fd7ad 100644 --- a/src/arch/x86/isa.hh +++ b/src/arch/x86/isa.hh @@ -85,6 +85,12 @@ namespace X86ISA return reg; } + int + flattenCCIndex(int reg) + { + return reg; + } + void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); void startup(ThreadContext *tc); diff --git a/src/arch/x86/registers.hh b/src/arch/x86/registers.hh index bb9f5f7b1..d62992dcd 100644 --- a/src/arch/x86/registers.hh +++ b/src/arch/x86/registers.hh @@ -57,6 +57,7 @@ const int NumIntArchRegs = NUM_INTREGS; const int NumIntRegs = NumIntArchRegs + NumMicroIntRegs + NumPseudoIntRegs + NumImplicitIntRegs; +const int NumCCRegs = 0; // Each 128 bit xmm register is broken into two effective 64 bit registers. // Add 8 for the indices that are mapped over the fp stack @@ -69,7 +70,8 @@ enum DependenceTags { // register index which has the IntFoldBit (1 << 6) set. To be safe // we just start at (1 << 7) == 128. FP_Reg_Base = 128, - Misc_Reg_Base = FP_Reg_Base + NumFloatRegs, + CC_Reg_Base = FP_Reg_Base + NumFloatRegs, + Misc_Reg_Base = CC_Reg_Base + NumCCRegs, // NumCCRegs == 0 Max_Reg_Index = Misc_Reg_Base + NumMiscRegs }; @@ -87,6 +89,7 @@ const int FramePointerReg = INTREG_RBP; const int SyscallPseudoReturnReg = INTREG_RDX; typedef uint64_t IntReg; +typedef uint64_t CCReg; //XXX Should this be a 128 bit structure for XMM memory ops? typedef uint64_t LargestRead; typedef uint64_t MiscReg; diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index b50b99dfa..df7d3935d 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -244,6 +244,8 @@ copyRegs(ThreadContext *src, ThreadContext *dest) //copy float regs for (int i = 0; i < NumFloatRegs; ++i) dest->setFloatRegBits(i, src->readFloatRegBits(i)); + // Will need to add condition-code regs when implemented + assert(NumCCRegs == 0); copyMiscRegs(src, dest); dest->pcState(src->pcState()); } diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 8989a438a..6aecd32dc 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011,2013 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -633,6 +634,12 @@ class BaseDynInst : public RefCounted setResult<uint64_t>(val); } + /** Records a CC register being set to a value. */ + void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + { + setResult<uint64_t>(val); + } + /** Records an fp register being set to a value. */ void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, int width) diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 637481706..c49f264f9 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -223,6 +224,12 @@ class CheckerCPU : public BaseCPU return thread->readFloatRegBits(reg_idx); } + uint64_t readCCRegOperand(const StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::CC_Reg_Base; + return thread->readCCReg(reg_idx); + } + template <class T> void setResult(T t) { @@ -252,6 +259,13 @@ class CheckerCPU : public BaseCPU setResult<uint64_t>(val); } + void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::CC_Reg_Base; + thread->setCCReg(reg_idx, val); + setResult<uint64_t>(val); + } + bool readPredicate() { return thread->readPredicate(); } void setPredicate(bool val) { diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 185fed88e..e18644e0e 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -606,6 +606,9 @@ Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val, case FloatRegClass: thread->setFloatRegBits(idx, mismatch_val); break; + case CCRegClass: + thread->setCCReg(idx, mismatch_val); + break; case MiscRegClass: thread->setMiscReg(idx - TheISA::Misc_Reg_Base, mismatch_val); @@ -624,6 +627,9 @@ Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val, case FloatRegClass: thread->setFloatRegBits(idx, res); break; + case CCRegClass: + thread->setCCReg(idx, res); + break; case MiscRegClass: // Try to get the proper misc register index for ARM here... thread->setMiscReg(idx - TheISA::Misc_Reg_Base, res); diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 80726ff19..c06e03fc6 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -216,6 +217,9 @@ class CheckerThreadContext : public ThreadContext FloatRegBits readFloatRegBits(int reg_idx) { return actualTC->readFloatRegBits(reg_idx); } + CCReg readCCReg(int reg_idx) + { return actualTC->readCCReg(reg_idx); } + void setIntReg(int reg_idx, uint64_t val) { actualTC->setIntReg(reg_idx, val); @@ -234,6 +238,12 @@ class CheckerThreadContext : public ThreadContext checkerTC->setFloatRegBits(reg_idx, val); } + void setCCReg(int reg_idx, CCReg val) + { + actualTC->setCCReg(reg_idx, val); + checkerTC->setCCReg(reg_idx, val); + } + /** Reads this thread's PC state. */ TheISA::PCState pcState() { return actualTC->pcState(); } @@ -289,6 +299,7 @@ class CheckerThreadContext : public ThreadContext int flattenIntIndex(int reg) { return actualTC->flattenIntIndex(reg); } int flattenFloatIndex(int reg) { return actualTC->flattenFloatIndex(reg); } + int flattenCCIndex(int reg) { return actualTC->flattenCCIndex(reg); } unsigned readStCondFailures() { return actualTC->readStCondFailures(); } @@ -320,6 +331,12 @@ class CheckerThreadContext : public ThreadContext void setFloatRegBitsFlat(int idx, FloatRegBits val) { actualTC->setFloatRegBitsFlat(idx, val); } + + CCReg readCCRegFlat(int idx) + { return actualTC->readCCRegFlat(idx); } + + void setCCRegFlat(int idx, CCReg val) + { actualTC->setCCRegFlat(idx, val); } }; #endif // __CPU_CHECKER_EXEC_CONTEXT_HH__ diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 32ca2caaf..5a02f94d9 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -361,6 +361,9 @@ InOrderCPU::InOrderCPU(Params *params) memset(intRegs[tid], 0, sizeof(intRegs[tid])); memset(floatRegs.i[tid], 0, sizeof(floatRegs.i[tid])); +#ifdef ISA_HAS_CC_REGS + memset(ccRegs[tid], 0, sizeof(ccRegs[tid])); +#endif isa[tid]->clear(); // Define dummy instructions and resource requests to be used. @@ -1305,6 +1308,19 @@ InOrderCPU::readFloatRegBits(RegIndex reg_idx, ThreadID tid) return floatRegs.i[tid][reg_idx]; } +CCReg +InOrderCPU::readCCReg(RegIndex reg_idx, ThreadID tid) +{ +#ifdef ISA_HAS_CC_REGS + DPRINTF(CCRegs, "[tid:%i]: Reading CC. Reg %i as %x\n", + tid, reg_idx, ccRegs[tid][reg_idx]); + + return ccRegs[tid][reg_idx]; +#else + panic("readCCReg: ISA does not have CC regs\n"); +#endif +} + void InOrderCPU::setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid) { @@ -1344,6 +1360,18 @@ InOrderCPU::setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid) floatRegs.f[tid][reg_idx]); } +void +InOrderCPU::setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid) +{ +#ifdef ISA_HAS_CC_REGS + DPRINTF(CCRegs, "[tid:%i]: Setting CC. Reg %i to %x\n", + tid, reg_idx, val); + ccRegs[tid][reg_idx] = val; +#else + panic("readCCReg: ISA does not have CC regs\n"); +#endif +} + uint64_t InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid) { @@ -1391,6 +1419,10 @@ InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val, setFloatRegBits(rel_idx, val, tid); break; + case CCRegClass: + setCCReg(rel_idx, val, tid); + break; + case MiscRegClass: setMiscReg(rel_idx, val, tid); // Misc. Register File break; diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index d5a31cca8..1183f6fc9 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -93,6 +93,7 @@ class InOrderCPU : public BaseCPU typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::CCReg CCReg; typedef TheISA::MiscReg MiscReg; typedef TheISA::RegIndex RegIndex; @@ -327,6 +328,9 @@ class InOrderCPU : public BaseCPU FloatRegBits i[ThePipeline::MaxThreads][TheISA::NumFloatRegs]; } floatRegs; TheISA::IntReg intRegs[ThePipeline::MaxThreads][TheISA::NumIntRegs]; +#ifdef ISA_HAS_CC_REGS + TheISA::CCReg ccRegs[ThePipeline::MaxThreads][TheISA::NumCCRegs]; +#endif /** ISA state */ std::vector<TheISA::ISA *> isa; @@ -590,12 +594,16 @@ class InOrderCPU : public BaseCPU FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid); + CCReg readCCReg(RegIndex reg_idx, ThreadID tid); + void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid); void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid); void setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid); + void setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid); + RegIndex flattenRegIdx(RegIndex reg_idx, RegClass ®_type, ThreadID tid); /** Reads a miscellaneous register. */ diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index c2765a3ba..aedc630f5 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -562,6 +562,10 @@ InOrderDynInst::setRegOtherThread(unsigned reg_idx, const MiscReg &val, this->cpu->setFloatRegBits(rel_idx, val, tid); break; + case CCRegClass: + this->cpu->setCCReg(rel_idx, val, tid); + break; + case MiscRegClass: this->cpu->setMiscReg(rel_idx, val, tid); // Misc. Register File break; diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index afd137a2e..48c15e292 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -1,6 +1,7 @@ /* * Copyright (c) 2007 MIPS Technologies, Inc. * Copyright (c) 2004-2006 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,6 +88,8 @@ class InOrderDynInst : public RefCounted typedef TheISA::FloatReg FloatReg; // Floating point register type. typedef TheISA::FloatRegBits FloatRegBits; + // Condition code register type. + typedef TheISA::CCReg CCReg; // Floating point register type. typedef TheISA::MiscReg MiscReg; @@ -880,6 +883,11 @@ class InOrderDynInst : public RefCounted return instResult[idx].res.fpVal.i; } + CCReg readCCResult(int idx) + { + return instResult[idx].res.intVal; + } + Tick readResultTime(int idx) { return instResult[idx].tick; } IntReg* getIntResultPtr(int idx) { return &instResult[idx].res.intVal; } @@ -891,6 +899,7 @@ class InOrderDynInst : public RefCounted void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val); void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val); + void setCCRegOperand(const StaticInst *si, int idx, CCReg val); void setMiscReg(int misc_reg, const MiscReg &val); void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val); diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index aab8c226a..763cc6df2 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -190,6 +191,14 @@ InOrderThreadContext::readFloatRegBits(int reg_idx) return cpu->readFloatRegBits(reg_idx, tid); } +CCReg +InOrderThreadContext::readCCReg(int reg_idx) +{ + ThreadID tid = thread->threadId(); + reg_idx = cpu->isa[tid]->flattenCCIndex(reg_idx); + return cpu->readCCReg(reg_idx, tid); +} + uint64_t InOrderThreadContext::readRegOtherThread(int reg_idx, ThreadID tid) { @@ -221,6 +230,14 @@ InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val) } void +InOrderThreadContext::setCCReg(int reg_idx, CCReg val) +{ + ThreadID tid = thread->threadId(); + reg_idx = cpu->isa[tid]->flattenCCIndex(reg_idx); + cpu->setCCReg(reg_idx, val, tid); +} + +void InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val, ThreadID tid) { @@ -281,3 +298,17 @@ InOrderThreadContext::setFloatRegBitsFlat(int idx, FloatRegBits val) const ThreadID tid = thread->threadId(); cpu->setFloatRegBits(idx, val, tid); } + +CCReg +InOrderThreadContext::readCCRegFlat(int idx) +{ + const ThreadID tid = thread->threadId(); + return cpu->readCCReg(idx, tid); +} + +void +InOrderThreadContext::setCCRegFlat(int idx, CCReg val) +{ + const ThreadID tid = thread->threadId(); + cpu->setCCReg(idx, val, tid); +} diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index f4847d0b4..5e1c65f8f 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -207,6 +208,8 @@ class InOrderThreadContext : public ThreadContext FloatRegBits readFloatRegBits(int reg_idx); + CCReg readCCReg(int reg_idx); + uint64_t readRegOtherThread(int misc_reg, ThreadID tid); /** Sets an integer register to a value. */ @@ -216,6 +219,8 @@ class InOrderThreadContext : public ThreadContext void setFloatRegBits(int reg_idx, FloatRegBits val); + void setCCReg(int reg_idx, CCReg val); + void setRegOtherThread(int misc_reg, const MiscReg &val, ThreadID tid); @@ -265,6 +270,9 @@ class InOrderThreadContext : public ThreadContext int flattenFloatIndex(int reg) { return cpu->isa[thread->threadId()]->flattenFloatIndex(reg); } + int flattenCCIndex(int reg) + { return cpu->isa[thread->threadId()]->flattenCCIndex(reg); } + void activateContext(Cycles delay) { cpu->activateContext(thread->threadId(), delay); } @@ -307,6 +315,9 @@ class InOrderThreadContext : public ThreadContext FloatRegBits readFloatRegBitsFlat(int idx); void setFloatRegBitsFlat(int idx, FloatRegBits val); + + CCReg readCCRegFlat(int idx); + void setCCRegFlat(int idx, CCReg val); }; #endif diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index e19881248..4b94f3581 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -112,6 +112,7 @@ class DerivO3CPU(BaseCPU): numPhysIntRegs = Param.Unsigned(256, "Number of physical integer registers") numPhysFloatRegs = Param.Unsigned(256, "Number of physical floating point " "registers") + numPhysCCRegs = Param.Unsigned(0, "Number of physical cc registers") numIQEntries = Param.Unsigned(64, "Number of instruction queue entries") numROBEntries = Param.Unsigned(192, "Number of reorder buffer entries") diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 3e33e139a..f379b1068 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -225,7 +225,8 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) commit(this, params), regFile(params->numPhysIntRegs, - params->numPhysFloatRegs), + params->numPhysFloatRegs, + params->numPhysCCRegs), freeList(name() + ".freelist", ®File), @@ -327,6 +328,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) //Make Sure That this a Valid Architeture assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); + assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); rename.setScoreboard(&scoreboard); iew.setScoreboard(&scoreboard); @@ -368,6 +370,12 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) renameMap[tid].setFloatEntry(ridx, phys_reg); commitRenameMap[tid].setFloatEntry(ridx, phys_reg); } + + for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { + PhysRegIndex phys_reg = freeList.getCCReg(); + renameMap[tid].setCCEntry(ridx, phys_reg); + commitRenameMap[tid].setCCEntry(ridx, phys_reg); + } } rename.setRenameMap(renameMap); @@ -555,6 +563,16 @@ FullO3CPU<Impl>::regStats() .desc("number of floating regfile writes") .prereq(fpRegfileWrites); + ccRegfileReads + .name(name() + ".cc_regfile_reads") + .desc("number of cc regfile reads") + .prereq(ccRegfileReads); + + ccRegfileWrites + .name(name() + ".cc_regfile_writes") + .desc("number of cc regfile writes") + .prereq(ccRegfileWrites); + miscRegfileReads .name(name() + ".misc_regfile_reads") .desc("number of misc regfile reads") @@ -842,13 +860,24 @@ FullO3CPU<Impl>::insertThread(ThreadID tid) } //Bind Float Regs to Rename Map - for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { + int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs; + for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) { PhysRegIndex phys_reg = freeList.getFloatReg(); renameMap[tid].setEntry(freg,phys_reg); scoreboard.setReg(phys_reg); } + //Bind condition-code Regs to Rename Map + max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs; + for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs; + creg < max_reg; creg++) { + PhysRegIndex phys_reg = freeList.getCCReg(); + + renameMap[tid].setEntry(creg,phys_reg); + scoreboard.setReg(phys_reg); + } + //Copy Thread Data Into RegFile //this->copyFromTC(tid); @@ -888,13 +917,24 @@ FullO3CPU<Impl>::removeThread(ThreadID tid) } // Unbind Float Regs from Rename Map - for (int freg = TheISA::NumIntRegs; freg < TheISA::NumFloatRegs; freg++) { + int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs; + for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) { PhysRegIndex phys_reg = renameMap[tid].lookup(freg); scoreboard.unsetReg(phys_reg); freeList.addReg(phys_reg); } + // Unbind condition-code Regs from Rename Map + max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs; + for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs; + creg < max_reg; creg++) { + PhysRegIndex phys_reg = renameMap[tid].lookup(creg); + + scoreboard.unsetReg(phys_reg); + freeList.addReg(phys_reg); + } + // Squash Throughout Pipeline DynInstPtr inst = commit.rob->readHeadInst(tid); InstSeqNum squash_seq_num = inst->seqNum; @@ -934,6 +974,7 @@ FullO3CPU<Impl>::activateWhenReady(ThreadID tid) bool ready = true; + // Should these all be '<' not '>='? This seems backwards... if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " "Phys. Int. Regs.\n", @@ -944,6 +985,11 @@ FullO3CPU<Impl>::activateWhenReady(ThreadID tid) "Phys. Float. Regs.\n", tid); ready = false; + } else if (freeList.numFreeCCRegs() >= TheISA::NumCCRegs) { + DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " + "Phys. CC. Regs.\n", + tid); + ready = false; } else if (commit.rob->numFreeEntries() >= commit.rob->entryAmount(activeThreads.size() + 1)) { DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " @@ -1366,6 +1412,14 @@ FullO3CPU<Impl>::readFloatRegBits(int reg_idx) } template <class Impl> +CCReg +FullO3CPU<Impl>::readCCReg(int reg_idx) +{ + ccRegfileReads++; + return regFile.readCCReg(reg_idx); +} + +template <class Impl> void FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) { @@ -1390,6 +1444,14 @@ FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) } template <class Impl> +void +FullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val) +{ + ccRegfileWrites++; + regFile.setCCReg(reg_idx, val); +} + +template <class Impl> uint64_t FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) { @@ -1420,6 +1482,16 @@ FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) } template <class Impl> +CCReg +FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) +{ + ccRegfileReads++; + PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); + + return regFile.readCCReg(phys_reg); +} + +template <class Impl> void FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) { @@ -1450,6 +1522,16 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) } template <class Impl> +void +FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) +{ + ccRegfileWrites++; + PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); + + regFile.setCCReg(phys_reg, val); +} + +template <class Impl> TheISA::PCState FullO3CPU<Impl>::pcState(ThreadID tid) { diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 1a1f8f8a3..18b75948f 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -540,18 +540,24 @@ class FullO3CPU : public BaseO3CPU TheISA::FloatRegBits readFloatRegBits(int reg_idx); + TheISA::CCReg readCCReg(int reg_idx); + void setIntReg(int reg_idx, uint64_t val); void setFloatReg(int reg_idx, TheISA::FloatReg val); void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val); + void setCCReg(int reg_idx, TheISA::CCReg val); + uint64_t readArchIntReg(int reg_idx, ThreadID tid); float readArchFloatReg(int reg_idx, ThreadID tid); uint64_t readArchFloatRegInt(int reg_idx, ThreadID tid); + TheISA::CCReg readArchCCReg(int reg_idx, ThreadID tid); + /** Architectural register accessors. Looks up in the commit * rename table to obtain the true physical index of the * architected register first, then accesses that physical @@ -563,6 +569,8 @@ class FullO3CPU : public BaseO3CPU void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid); + void setArchCCReg(int reg_idx, TheISA::CCReg val, ThreadID tid); + /** Sets the commit PC state of a specific thread. */ void pcState(const TheISA::PCState &newPCState, ThreadID tid); @@ -846,6 +854,9 @@ class FullO3CPU : public BaseO3CPU //number of float register file accesses Stats::Scalar fpRegfileReads; Stats::Scalar fpRegfileWrites; + //number of CC register file accesses + Stats::Scalar ccRegfileReads; + Stats::Scalar ccRegfileWrites; //number of misc Stats::Scalar miscRegfileReads; Stats::Scalar miscRegfileWrites; diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 15a82851b..5477f46d6 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -78,6 +78,9 @@ class BaseO3DynInst : public BaseDynInst<Impl> typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; +#ifdef ISA_HAS_CC_REGS + typedef TheISA::CCReg CCReg; +#endif /** Misc register index type. */ typedef TheISA::MiscReg MiscReg; @@ -222,6 +225,10 @@ class BaseO3DynInst : public BaseDynInst<Impl> this->setFloatRegOperandBits(this->staticInst.get(), idx, this->cpu->readFloatRegBits(prev_phys_reg)); break; + case CCRegClass: + this->setCCRegOperand(this->staticInst.get(), idx, + this->cpu->readCCReg(prev_phys_reg)); + break; case MiscRegClass: // no need to forward misc reg values break; @@ -265,6 +272,11 @@ class BaseO3DynInst : public BaseDynInst<Impl> return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } + uint64_t readCCRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readCCReg(this->_srcRegIdx[idx]); + } + /** @todo: Make results into arrays so they can handle multiple dest * registers. */ @@ -287,6 +299,12 @@ class BaseO3DynInst : public BaseDynInst<Impl> BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } + void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + { + this->cpu->setCCReg(this->_destRegIdx[idx], val); + BaseDynInst<Impl>::setCCRegOperand(si, idx, val); + } + #if THE_ISA == MIPS_ISA uint64_t readRegOtherThread(int misc_reg) { diff --git a/src/cpu/o3/free_list.cc b/src/cpu/o3/free_list.cc index 0c8a16d0d..a9544587e 100644 --- a/src/cpu/o3/free_list.cc +++ b/src/cpu/o3/free_list.cc @@ -29,7 +29,9 @@ * Authors: Kevin Lim */ +#include "arch/registers.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/o3/free_list.hh" #include "debug/FreeList.hh" diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh index 3919d0afb..aa805e26e 100644 --- a/src/cpu/o3/free_list.hh +++ b/src/cpu/o3/free_list.hh @@ -106,6 +106,9 @@ class UnifiedFreeList /** The list of free floating point registers. */ SimpleFreeList floatList; + /** The list of free condition-code registers. */ + SimpleFreeList ccList; + /** * The register file object is used only to distinguish integer * from floating-point physical register indices. @@ -133,12 +136,18 @@ class UnifiedFreeList /** Gives the name of the freelist. */ std::string name() const { return _name; }; + /** Returns a pointer to the condition-code free list */ + SimpleFreeList *getCCList() { return &ccList; } + /** Gets a free integer register. */ PhysRegIndex getIntReg() { return intList.getReg(); } /** Gets a free fp register. */ PhysRegIndex getFloatReg() { return floatList.getReg(); } + /** Gets a free cc register. */ + PhysRegIndex getCCReg() { return ccList.getReg(); } + /** Adds a register back to the free list. */ void addReg(PhysRegIndex freed_reg); @@ -148,17 +157,26 @@ class UnifiedFreeList /** Adds a fp register back to the free list. */ void addFloatReg(PhysRegIndex freed_reg) { floatList.addReg(freed_reg); } + /** Adds a cc register back to the free list. */ + void addCCReg(PhysRegIndex freed_reg) { ccList.addReg(freed_reg); } + /** Checks if there are any free integer registers. */ bool hasFreeIntRegs() const { return intList.hasFreeRegs(); } /** Checks if there are any free fp registers. */ bool hasFreeFloatRegs() const { return floatList.hasFreeRegs(); } + /** Checks if there are any free cc registers. */ + bool hasFreeCCRegs() const { return ccList.hasFreeRegs(); } + /** Returns the number of free integer registers. */ unsigned numFreeIntRegs() const { return intList.numFreeRegs(); } /** Returns the number of free fp registers. */ unsigned numFreeFloatRegs() const { return floatList.numFreeRegs(); } + + /** Returns the number of free cc registers. */ + unsigned numFreeCCRegs() const { return ccList.numFreeRegs(); } }; inline void @@ -169,9 +187,11 @@ UnifiedFreeList::addReg(PhysRegIndex freed_reg) //already in there. A bit vector or something similar would be useful. if (regFile->isIntPhysReg(freed_reg)) { intList.addReg(freed_reg); - } else { - assert(regFile->isFloatPhysReg(freed_reg)); + } else if (regFile->isFloatPhysReg(freed_reg)) { floatList.addReg(freed_reg); + } else { + assert(regFile->isCCPhysReg(freed_reg)); + ccList.addReg(freed_reg); } // These assert conditions ensure that the number of free diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index 15190970d..212829ec1 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -414,12 +415,6 @@ class InstructionQueue /** The number of physical registers in the CPU. */ unsigned numPhysRegs; - /** The number of physical integer registers in the CPU. */ - unsigned numPhysIntRegs; - - /** The number of floating point registers in the CPU. */ - unsigned numPhysFloatRegs; - /** Delay between commit stage and the IQ. * @todo: Make there be a distinction between the delays within IEW. */ diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 3e3325beb..1c86b7c89 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -87,16 +88,15 @@ InstructionQueue<Impl>::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, fuPool(params->fuPool), numEntries(params->numIQEntries), totalWidth(params->issueWidth), - numPhysIntRegs(params->numPhysIntRegs), - numPhysFloatRegs(params->numPhysFloatRegs), commitToIEWDelay(params->commitToIEWDelay) { assert(fuPool); numThreads = params->numThreads; - // Set the number of physical registers as the number of int + float - numPhysRegs = numPhysIntRegs + numPhysFloatRegs; + // Set the number of total physical registers + numPhysRegs = params->numPhysIntRegs + params->numPhysFloatRegs + + params->numPhysCCRegs; //Create an entry for each physical register within the //dependency graph. diff --git a/src/cpu/o3/regfile.cc b/src/cpu/o3/regfile.cc index 5ba0caefc..96ce44bdd 100644 --- a/src/cpu/o3/regfile.cc +++ b/src/cpu/o3/regfile.cc @@ -36,12 +36,23 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, - unsigned _numPhysicalFloatRegs) + unsigned _numPhysicalFloatRegs, + unsigned _numPhysicalCCRegs) : intRegFile(_numPhysicalIntRegs), floatRegFile(_numPhysicalFloatRegs), + ccRegFile(_numPhysicalCCRegs), baseFloatRegIndex(_numPhysicalIntRegs), - totalNumRegs(_numPhysicalIntRegs + _numPhysicalFloatRegs) + baseCCRegIndex(_numPhysicalIntRegs + _numPhysicalFloatRegs), + totalNumRegs(_numPhysicalIntRegs + + _numPhysicalFloatRegs + + _numPhysicalCCRegs) { + if (TheISA::NumCCRegs == 0 && _numPhysicalCCRegs != 0) { + // Just make this a warning and go ahead and allocate them + // anyway, to keep from having to add checks everywhere + warn("Non-zero number of physical CC regs specified, even though\n" + " ISA does not use them.\n"); + } } @@ -56,9 +67,15 @@ PhysRegFile::initFreeList(UnifiedFreeList *freeList) freeList->addIntReg(reg_idx++); } - // The rest of the registers are the floating-point physical + // The next batch of the registers are the floating-point physical // registers; put them onto the floating-point free list. - while (reg_idx < totalNumRegs) { + while (reg_idx < baseCCRegIndex) { freeList->addFloatReg(reg_idx++); } + + // The rest of the registers are the condition-code physical + // registers; put them onto the condition-code free list. + while (reg_idx < totalNumRegs) { + freeList->addCCReg(reg_idx++); + } } diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index bd3a4f730..8b87725ca 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -55,6 +55,7 @@ class PhysRegFile typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::CCReg CCReg; typedef union { FloatReg d; @@ -67,6 +68,9 @@ class PhysRegFile /** Floating point register file. */ std::vector<PhysFloatReg> floatRegFile; + /** Condition-code register file. */ + std::vector<CCReg> ccRegFile; + /** * The first floating-point physical register index. The physical * register file has a single continuous index space, with the @@ -83,6 +87,12 @@ class PhysRegFile */ unsigned baseFloatRegIndex; + /** + * The first condition-code physical register index. The + * condition-code registers follow the floating-point registers. + */ + unsigned baseCCRegIndex; + /** Total number of physical registers. */ unsigned totalNumRegs; @@ -92,7 +102,8 @@ class PhysRegFile * integer and floating point registers. */ PhysRegFile(unsigned _numPhysicalIntRegs, - unsigned _numPhysicalFloatRegs); + unsigned _numPhysicalFloatRegs, + unsigned _numPhysicalCCRegs); /** * Destructor to free resources @@ -107,7 +118,11 @@ class PhysRegFile /** @return the number of floating-point physical registers. */ unsigned numFloatPhysRegs() const - { return totalNumRegs - baseFloatRegIndex; } + { return baseCCRegIndex - baseFloatRegIndex; } + + /** @return the number of condition-code physical registers. */ + unsigned numCCPhysRegs() const + { return totalNumRegs - baseCCRegIndex; } /** @return the total number of physical registers. */ unsigned totalNumPhysRegs() const { return totalNumRegs; } @@ -127,7 +142,16 @@ class PhysRegFile */ bool isFloatPhysReg(PhysRegIndex reg_idx) const { - return (baseFloatRegIndex <= reg_idx && reg_idx < totalNumRegs); + return (baseFloatRegIndex <= reg_idx && reg_idx < baseCCRegIndex); + } + + /** + * Return true if the specified physical register index + * corresponds to a condition-code physical register. + */ + bool isCCPhysReg(PhysRegIndex reg_idx) + { + return (baseCCRegIndex <= reg_idx && reg_idx < totalNumRegs); } /** Reads an integer register. */ @@ -169,6 +193,20 @@ class PhysRegFile return floatRegBits; } + /** Reads a condition-code register. */ + CCReg readCCReg(PhysRegIndex reg_idx) + { + assert(isCCPhysReg(reg_idx)); + + // Remove the base CC reg dependency. + PhysRegIndex reg_offset = reg_idx - baseCCRegIndex; + + DPRINTF(IEW, "RegFile: Access to cc register %i, has " + "data %#x\n", int(reg_idx), ccRegFile[reg_offset]); + + return ccRegFile[reg_offset]; + } + /** Sets an integer register to the given value. */ void setIntReg(PhysRegIndex reg_idx, uint64_t val) { @@ -211,6 +249,19 @@ class PhysRegFile floatRegFile[reg_offset].q = val; } + /** Sets a condition-code register to the given value. */ + void setCCReg(PhysRegIndex reg_idx, CCReg val) + { + assert(isCCPhysReg(reg_idx)); + + // Remove the base CC reg dependency. + PhysRegIndex reg_offset = reg_idx - baseCCRegIndex; + + DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n", + int(reg_idx), (uint64_t)val); + + ccRegFile[reg_offset] = val; + } }; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 6bfc7d952..38191ce36 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -65,7 +65,8 @@ DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params) renameWidth(params->renameWidth), commitWidth(params->commitWidth), numThreads(params->numThreads), - maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs) + maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs + + params->numPhysCCRegs) { // @todo: Make into a parameter. skidBufferMax = (2 * (decodeToRenameDelay * params->decodeWidth)) + renameWidth; @@ -974,6 +975,11 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid) fpRenameLookups++; break; + case CCRegClass: + flat_rel_src_reg = tc->flattenCCIndex(rel_src_reg); + renamed_reg = map->lookupCC(flat_rel_src_reg); + break; + case MiscRegClass: // misc regs don't get flattened flat_rel_src_reg = rel_src_reg; @@ -1034,6 +1040,12 @@ DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid) flat_uni_dest_reg = flat_rel_dest_reg + TheISA::FP_Reg_Base; break; + case CCRegClass: + flat_rel_dest_reg = tc->flattenCCIndex(rel_dest_reg); + rename_result = map->renameCC(flat_rel_dest_reg); + flat_uni_dest_reg = flat_rel_dest_reg + TheISA::CC_Reg_Base; + break; + case MiscRegClass: // misc regs don't get flattened flat_rel_dest_reg = rel_dest_reg; diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc index ecee4c721..d816bf1fd 100644 --- a/src/cpu/o3/rename_map.cc +++ b/src/cpu/o3/rename_map.cc @@ -97,6 +97,8 @@ UnifiedRenameMap::init(PhysRegFile *_regFile, intMap.init(TheISA::NumIntRegs, &(freeList->intList), _intZeroReg); floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg); + + ccMap.init(TheISA::NumFloatRegs, &(freeList->ccList), (RegIndex)-1); } @@ -112,6 +114,9 @@ UnifiedRenameMap::rename(RegIndex arch_reg) case FloatRegClass: return renameFloat(rel_arch_reg); + case CCRegClass: + return renameCC(rel_arch_reg); + case MiscRegClass: return renameMisc(rel_arch_reg); @@ -134,6 +139,9 @@ UnifiedRenameMap::lookup(RegIndex arch_reg) const case FloatRegClass: return lookupFloat(rel_arch_reg); + case CCRegClass: + return lookupCC(rel_arch_reg); + case MiscRegClass: return lookupMisc(rel_arch_reg); @@ -155,6 +163,9 @@ UnifiedRenameMap::setEntry(RegIndex arch_reg, PhysRegIndex phys_reg) case FloatRegClass: return setFloatEntry(rel_arch_reg, phys_reg); + case CCRegClass: + return setCCEntry(rel_arch_reg, phys_reg); + case MiscRegClass: // Misc registers do not actually rename, so don't change // their mappings. We end up here when a commit or squash diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh index c989fb88f..751c39f52 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -163,6 +163,9 @@ class UnifiedRenameMap */ PhysRegFile *regFile; + /** The condition-code register rename map */ + SimpleRenameMap ccMap; + public: typedef TheISA::RegIndex RegIndex; @@ -214,6 +217,17 @@ class UnifiedRenameMap } /** + * Perform rename() on a condition-code register, given a relative + * condition-code register index. + */ + RenameInfo renameCC(RegIndex rel_arch_reg) + { + RenameInfo info = ccMap.rename(rel_arch_reg); + assert(regFile->isCCPhysReg(info.first)); + return info; + } + + /** * Perform rename() on a misc register, given a relative * misc register index. */ @@ -260,6 +274,17 @@ class UnifiedRenameMap } /** + * Perform lookup() on a condition-code register, given a relative + * condition-code register index. + */ + PhysRegIndex lookupCC(RegIndex rel_arch_reg) const + { + PhysRegIndex phys_reg = ccMap.lookup(rel_arch_reg); + assert(regFile->isCCPhysReg(phys_reg)); + return phys_reg; + } + + /** * Perform lookup() on a misc register, given a relative * misc register index. */ @@ -302,6 +327,16 @@ class UnifiedRenameMap } /** + * Perform setEntry() on a condition-code register, given a relative + * condition-code register index. + */ + void setCCEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + { + assert(regFile->isCCPhysReg(phys_reg)); + ccMap.setEntry(arch_reg, phys_reg); + } + + /** * Return the minimum number of free entries across all of the * register classes. The minimum is used so we guarantee that * this number of entries is available regardless of which class diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 4201878af..88cf75f4f 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -182,6 +183,10 @@ class O3ThreadContext : public ThreadContext return readFloatRegBitsFlat(flattenFloatIndex(reg_idx)); } + virtual CCReg readCCReg(int reg_idx) { + return readCCRegFlat(flattenCCIndex(reg_idx)); + } + /** Sets an integer register to a value. */ virtual void setIntReg(int reg_idx, uint64_t val) { setIntRegFlat(flattenIntIndex(reg_idx), val); @@ -195,6 +200,10 @@ class O3ThreadContext : public ThreadContext setFloatRegBitsFlat(flattenFloatIndex(reg_idx), val); } + virtual void setCCReg(int reg_idx, CCReg val) { + setCCRegFlat(flattenCCIndex(reg_idx), val); + } + /** Reads this thread's PC state. */ virtual TheISA::PCState pcState() { return cpu->pcState(thread->threadId()); } @@ -234,6 +243,7 @@ class O3ThreadContext : public ThreadContext virtual int flattenIntIndex(int reg); virtual int flattenFloatIndex(int reg); + virtual int flattenCCIndex(int reg); /** Returns the number of consecutive store conditional failures. */ // @todo: Figure out where these store cond failures should go. @@ -283,6 +293,9 @@ class O3ThreadContext : public ThreadContext virtual FloatRegBits readFloatRegBitsFlat(int idx); virtual void setFloatRegBitsFlat(int idx, FloatRegBits val); + + virtual CCReg readCCRegFlat(int idx); + virtual void setCCRegFlat(int idx, CCReg val); }; #endif diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index f818cc3dc..006d325fc 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2010-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -206,6 +207,13 @@ O3ThreadContext<Impl>::readFloatRegBitsFlat(int reg_idx) } template <class Impl> +TheISA::CCReg +O3ThreadContext<Impl>::readCCRegFlat(int reg_idx) +{ + return cpu->readArchCCReg(reg_idx, thread->threadId()); +} + +template <class Impl> void O3ThreadContext<Impl>::setIntRegFlat(int reg_idx, uint64_t val) { @@ -234,6 +242,15 @@ O3ThreadContext<Impl>::setFloatRegBitsFlat(int reg_idx, FloatRegBits val) template <class Impl> void +O3ThreadContext<Impl>::setCCRegFlat(int reg_idx, TheISA::CCReg val) +{ + cpu->setArchCCReg(reg_idx, val, thread->threadId()); + + conditionalSquash(); +} + +template <class Impl> +void O3ThreadContext<Impl>::pcState(const TheISA::PCState &val) { cpu->pcState(val, thread->threadId()); @@ -265,6 +282,13 @@ O3ThreadContext<Impl>::flattenFloatIndex(int reg) } template <class Impl> +int +O3ThreadContext<Impl>::flattenCCIndex(int reg) +{ + return cpu->isa[thread->threadId()]->flattenCCIndex(reg); +} + +template <class Impl> void O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index fcab901cf..b4b49a55b 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -769,6 +770,13 @@ OzoneCPU<Impl>::OzoneTC::readFloatRegBits(int reg_idx) } template <class Impl> +CCReg +OzoneCPU<Impl>::OzoneTC::readCCReg(int reg_idx) +{ + return thread->renameTable[reg_idx]->readCCResult(); +} + +template <class Impl> void OzoneCPU<Impl>::OzoneTC::setIntReg(int reg_idx, uint64_t val) { @@ -801,6 +809,17 @@ OzoneCPU<Impl>::OzoneTC::setFloatRegBits(int reg_idx, FloatRegBits val) template <class Impl> void +OzoneCPU<Impl>::OzoneTC::setCCReg(int reg_idx, CCReg val) +{ + thread->renameTable[reg_idx]->setCCResult(val); + + if (!thread->noSquashFromTC) { + cpu->squashFromTC(); + } +} + +template <class Impl> +void OzoneCPU<Impl>::OzoneTC::setPC(Addr val) { thread->PC = val; diff --git a/src/cpu/reg_class.cc b/src/cpu/reg_class.cc index a3de17b8b..1805eae13 100644 --- a/src/cpu/reg_class.cc +++ b/src/cpu/reg_class.cc @@ -33,5 +33,6 @@ const char *RegClassStrings[] = { "IntRegClass", "FloatRegClass", + "CCRegClass", "MiscRegClass" }; diff --git a/src/cpu/reg_class.hh b/src/cpu/reg_class.hh index c9d4b1c4f..549ebab26 100644 --- a/src/cpu/reg_class.hh +++ b/src/cpu/reg_class.hh @@ -41,6 +41,7 @@ enum RegClass { IntRegClass, ///< Integer register FloatRegClass, ///< Floating-point register + CCRegClass, ///< Condition-code register MiscRegClass ///< Control (misc) register }; @@ -72,9 +73,15 @@ RegClass regIdxToClass(TheISA::RegIndex reg_idx, if (reg_idx < TheISA::FP_Reg_Base) { cl = IntRegClass; offset = 0; - } else if (reg_idx < TheISA::Misc_Reg_Base) { + } else if (reg_idx < TheISA::CC_Reg_Base) { cl = FloatRegClass; offset = TheISA::FP_Reg_Base; + } else if (reg_idx < TheISA::Misc_Reg_Base) { + // if there are no CC regs, the ISA should set + // CC_Reg_Base == Misc_Reg_Base so the if above + // never succeeds + cl = CCRegClass; + offset = TheISA::CC_Reg_Base; } else { cl = MiscRegClass; offset = TheISA::Misc_Reg_Base; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 012a49253..078f490e8 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2010-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -211,6 +212,18 @@ BaseSimpleCPU::regStats() .desc("number of times the floating registers were written") ; + numCCRegReads + .name(name() + ".num_cc_register_reads") + .desc("number of times the CC registers were read") + .flags(nozero) + ; + + numCCRegWrites + .name(name() + ".num_cc_register_writes") + .desc("number of times the CC registers were written") + .flags(nozero) + ; + numMemRefs .name(name()+".num_mem_refs") .desc("number of memory refs") diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index f2e1b278a..8134465af 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -84,6 +85,7 @@ class BaseSimpleCPU : public BaseCPU typedef TheISA::MiscReg MiscReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::CCReg CCReg; protected: Trace::InstRecord *traceData; @@ -231,6 +233,10 @@ class BaseSimpleCPU : public BaseCPU Stats::Scalar numFpRegReads; Stats::Scalar numFpRegWrites; + //number of condition code register file accesses + Stats::Scalar numCCRegReads; + Stats::Scalar numCCRegWrites; + // number of simulated memory references Stats::Scalar numMemRefs; Stats::Scalar numLoadInsts; @@ -307,6 +313,13 @@ class BaseSimpleCPU : public BaseCPU return thread->readFloatRegBits(reg_idx); } + CCReg readCCRegOperand(const StaticInst *si, int idx) + { + numCCRegReads++; + int reg_idx = si->srcRegIdx(idx) - TheISA::CC_Reg_Base; + return thread->readCCReg(reg_idx); + } + void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) { numIntRegWrites++; @@ -328,6 +341,13 @@ class BaseSimpleCPU : public BaseCPU thread->setFloatRegBits(reg_idx, val); } + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) + { + numCCRegWrites++; + int reg_idx = si->destRegIdx(idx) - TheISA::CC_Reg_Base; + thread->setCCReg(reg_idx, val); + } + bool readPredicate() { return thread->readPredicate(); } void setPredicate(bool val) { diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index d752ed105..fa0d20b0a 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -54,6 +55,7 @@ #include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" +#include "debug/CCRegs.hh" #include "debug/FloatRegs.hh" #include "debug/IntRegs.hh" #include "mem/page_table.hh" @@ -99,6 +101,7 @@ class SimpleThread : public ThreadState typedef TheISA::MiscReg MiscReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::CCReg CCReg; public: typedef ThreadContext::Status Status; @@ -108,6 +111,9 @@ class SimpleThread : public ThreadState FloatRegBits i[TheISA::NumFloatRegs]; } floatRegs; TheISA::IntReg intRegs[TheISA::NumIntRegs]; +#ifdef ISA_HAS_CC_REGS + TheISA::CCReg ccRegs[TheISA::NumCCRegs]; +#endif TheISA::ISA *const isa; // one "instance" of the current ISA. TheISA::PCState _pcState; @@ -224,6 +230,9 @@ class SimpleThread : public ThreadState _pcState = 0; memset(intRegs, 0, sizeof(intRegs)); memset(floatRegs.i, 0, sizeof(floatRegs.i)); +#ifdef ISA_HAS_CC_REGS + memset(ccRegs, 0, sizeof(ccRegs)); +#endif isa->clear(); } @@ -260,6 +269,21 @@ class SimpleThread : public ThreadState return regVal; } + CCReg readCCReg(int reg_idx) + { +#ifdef ISA_HAS_CC_REGS + int flatIndex = isa->flattenCCIndex(reg_idx); + assert(flatIndex < TheISA::NumCCRegs); + uint64_t regVal(readCCRegFlat(flatIndex)); + DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n", + reg_idx, flatIndex, regVal); + return regVal; +#else + panic("Tried to read a CC register."); + return 0; +#endif + } + void setIntReg(int reg_idx, uint64_t val) { int flatIndex = isa->flattenIntIndex(reg_idx); @@ -290,6 +314,19 @@ class SimpleThread : public ThreadState reg_idx, flatIndex, val, floatRegs.f[flatIndex]); } + void setCCReg(int reg_idx, CCReg val) + { +#ifdef ISA_HAS_CC_REGS + int flatIndex = isa->flattenCCIndex(reg_idx); + assert(flatIndex < TheISA::NumCCRegs); + DPRINTF(CCRegs, "Setting CC reg %d (%d) to %#x.\n", + reg_idx, flatIndex, val); + setCCRegFlat(flatIndex, val); +#else + panic("Tried to set a CC register."); +#endif + } + TheISA::PCState pcState() { @@ -372,6 +409,12 @@ class SimpleThread : public ThreadState return isa->flattenFloatIndex(reg); } + int + flattenCCIndex(int reg) + { + return isa->flattenCCIndex(reg); + } + unsigned readStCondFailures() { return storeCondFailures; } void setStCondFailures(unsigned sc_failures) @@ -393,6 +436,16 @@ class SimpleThread : public ThreadState floatRegs.i[idx] = val; } +#ifdef ISA_HAS_CC_REGS + CCReg readCCRegFlat(int idx) { return ccRegs[idx]; } + void setCCRegFlat(int idx, CCReg val) { ccRegs[idx] = val; } +#else + CCReg readCCRegFlat(int idx) + { panic("readCCRegFlat w/no CC regs!\n"); } + + void setCCRegFlat(int idx, CCReg val) + { panic("setCCRegFlat w/no CC regs!\n"); } +#endif }; diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 0464eda14..66f254e34 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,6 +111,7 @@ class StaticInst : public RefCounted IsInteger, ///< References integer regs. IsFloating, ///< References FP regs. + IsCC, ///< References CC regs. IsMemRef, ///< References memory (load, store, or prefetch). IsLoad, ///< Reads from memory (load or prefetch). @@ -181,6 +183,7 @@ class StaticInst : public RefCounted //@{ int8_t _numFPDestRegs; int8_t _numIntDestRegs; + int8_t _numCCDestRegs; //@} public: @@ -220,6 +223,7 @@ class StaticInst : public RefCounted bool isInteger() const { return flags[IsInteger]; } bool isFloating() const { return flags[IsFloating]; } + bool isCC() const { return flags[IsCC]; } bool isControl() const { return flags[IsControl]; } bool isCall() const { return flags[IsCall]; } diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index a5a05a264..09f91746a 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -79,6 +80,14 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) i, t1, t2); } + // loop through the Condition Code registers. + for (int i = 0; i < TheISA::NumCCRegs; ++i) { + TheISA::CCReg t1 = one->readCCReg(i); + TheISA::CCReg t2 = two->readCCReg(i); + if (t1 != t2) + panic("CC reg idx %d doesn't match, one: %#x, two: %#x", + i, t1, t2); + } if (!(one->pcState() == two->pcState())) panic("PC state doesn't match."); int id1 = one->cpuId(); @@ -111,6 +120,13 @@ serialize(ThreadContext &tc, std::ostream &os) intRegs[i] = tc.readIntRegFlat(i); SERIALIZE_ARRAY(intRegs, NumIntRegs); +#ifdef ISA_HAS_CC_REGS + CCReg ccRegs[NumCCRegs]; + for (int i = 0; i < NumCCRegs; ++i) + ccRegs[i] = tc.readCCRegFlat(i); + SERIALIZE_ARRAY(ccRegs, NumCCRegs); +#endif + tc.pcState().serialize(os); // thread_num and cpu_id are deterministic from the config @@ -133,6 +149,13 @@ unserialize(ThreadContext &tc, Checkpoint *cp, const std::string §ion) for (int i = 0; i < NumIntRegs; ++i) tc.setIntRegFlat(i, intRegs[i]); +#ifdef ISA_HAS_CC_REGS + CCReg ccRegs[NumCCRegs]; + UNSERIALIZE_ARRAY(ccRegs, NumCCRegs); + for (int i = 0; i < NumCCRegs; ++i) + tc.setCCRegFlat(i, ccRegs[i]); +#endif + PCState pcState; pcState.unserialize(cp, section); tc.pcState(pcState); diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index dbe3c0ce8..be18f680f 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -96,6 +97,7 @@ class ThreadContext typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::CCReg CCReg; typedef TheISA::MiscReg MiscReg; public: @@ -200,12 +202,16 @@ class ThreadContext virtual FloatRegBits readFloatRegBits(int reg_idx) = 0; + virtual CCReg readCCReg(int reg_idx) = 0; + virtual void setIntReg(int reg_idx, uint64_t val) = 0; virtual void setFloatReg(int reg_idx, FloatReg val) = 0; virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0; + virtual void setCCReg(int reg_idx, CCReg val) = 0; + virtual TheISA::PCState pcState() = 0; virtual void pcState(const TheISA::PCState &val) = 0; @@ -228,6 +234,7 @@ class ThreadContext virtual int flattenIntIndex(int reg) = 0; virtual int flattenFloatIndex(int reg) = 0; + virtual int flattenCCIndex(int reg) = 0; virtual uint64_t readRegOtherThread(int misc_reg, ThreadID tid) @@ -283,6 +290,8 @@ class ThreadContext virtual FloatRegBits readFloatRegBitsFlat(int idx) = 0; virtual void setFloatRegBitsFlat(int idx, FloatRegBits val) = 0; + virtual CCReg readCCRegFlat(int idx) = 0; + virtual void setCCRegFlat(int idx, CCReg val) = 0; /** @} */ }; @@ -391,6 +400,9 @@ class ProxyThreadContext : public ThreadContext FloatRegBits readFloatRegBits(int reg_idx) { return actualTC->readFloatRegBits(reg_idx); } + CCReg readCCReg(int reg_idx) + { return actualTC->readCCReg(reg_idx); } + void setIntReg(int reg_idx, uint64_t val) { actualTC->setIntReg(reg_idx, val); } @@ -400,6 +412,9 @@ class ProxyThreadContext : public ThreadContext void setFloatRegBits(int reg_idx, FloatRegBits val) { actualTC->setFloatRegBits(reg_idx, val); } + void setCCReg(int reg_idx, CCReg val) + { actualTC->setCCReg(reg_idx, val); } + TheISA::PCState pcState() { return actualTC->pcState(); } void pcState(const TheISA::PCState &val) { actualTC->pcState(val); } @@ -433,6 +448,9 @@ class ProxyThreadContext : public ThreadContext int flattenFloatIndex(int reg) { return actualTC->flattenFloatIndex(reg); } + int flattenCCIndex(int reg) + { return actualTC->flattenCCIndex(reg); } + unsigned readStCondFailures() { return actualTC->readStCondFailures(); } @@ -464,6 +482,12 @@ class ProxyThreadContext : public ThreadContext void setFloatRegBitsFlat(int idx, FloatRegBits val) { actualTC->setFloatRegBitsFlat(idx, val); } + + CCReg readCCRegFlat(int idx) + { return actualTC->readCCRegFlat(idx); } + + void setCCRegFlat(int idx, CCReg val) + { actualTC->setCCRegFlat(idx, val); } }; /** @{ */ |