From 2c293823aa7cb6d2cac4c0ff35e2023ff132a8f2 Mon Sep 17 00:00:00 2001 From: Yasuko Eckert Date: Tue, 15 Oct 2013 14:22:44 -0400 Subject: [PATCH] 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. --- src/arch/SConscript | 3 +- src/arch/alpha/isa.hh | 7 +++ src/arch/alpha/registers.hh | 7 ++- src/arch/alpha/utility.cc | 3 + src/arch/arm/insts/static_inst.cc | 2 + src/arch/arm/isa.hh | 7 +++ src/arch/arm/registers.hh | 7 ++- src/arch/arm/utility.cc | 11 ++-- src/arch/isa_parser.py | 81 ++++++++++++++++++++++++++ src/arch/mips/isa.hh | 7 +++ src/arch/mips/registers.hh | 7 ++- src/arch/null/registers.hh | 1 + src/arch/power/insts/static_inst.cc | 2 + src/arch/power/isa.hh | 7 +++ src/arch/power/registers.hh | 7 ++- src/arch/power/utility.cc | 3 + src/arch/sparc/isa.hh | 7 +++ src/arch/sparc/registers.hh | 10 +++- src/arch/sparc/utility.cc | 3 + src/arch/x86/insts/static_inst.cc | 4 ++ src/arch/x86/isa.hh | 6 ++ src/arch/x86/registers.hh | 5 +- src/arch/x86/utility.cc | 2 + src/cpu/base_dyn_inst.hh | 7 +++ src/cpu/checker/cpu.hh | 14 +++++ src/cpu/checker/cpu_impl.hh | 6 ++ src/cpu/checker/thread_context.hh | 17 ++++++ src/cpu/inorder/cpu.cc | 32 +++++++++++ src/cpu/inorder/cpu.hh | 8 +++ src/cpu/inorder/inorder_dyn_inst.cc | 4 ++ src/cpu/inorder/inorder_dyn_inst.hh | 9 +++ src/cpu/inorder/thread_context.cc | 31 ++++++++++ src/cpu/inorder/thread_context.hh | 11 ++++ src/cpu/o3/O3CPU.py | 1 + src/cpu/o3/cpu.cc | 88 ++++++++++++++++++++++++++++- src/cpu/o3/cpu.hh | 11 ++++ src/cpu/o3/dyn_inst.hh | 18 ++++++ src/cpu/o3/free_list.cc | 2 + src/cpu/o3/free_list.hh | 24 +++++++- src/cpu/o3/inst_queue.hh | 7 +-- src/cpu/o3/inst_queue_impl.hh | 8 +-- src/cpu/o3/regfile.cc | 25 ++++++-- src/cpu/o3/regfile.hh | 57 ++++++++++++++++++- src/cpu/o3/rename_impl.hh | 14 ++++- src/cpu/o3/rename_map.cc | 11 ++++ src/cpu/o3/rename_map.hh | 35 ++++++++++++ src/cpu/o3/thread_context.hh | 13 +++++ src/cpu/o3/thread_context_impl.hh | 24 ++++++++ src/cpu/ozone/cpu_impl.hh | 19 +++++++ src/cpu/reg_class.cc | 1 + src/cpu/reg_class.hh | 9 ++- src/cpu/simple/base.cc | 13 +++++ src/cpu/simple/base.hh | 20 +++++++ src/cpu/simple_thread.hh | 53 +++++++++++++++++ src/cpu/static_inst.hh | 4 ++ src/cpu/thread_context.cc | 23 ++++++++ src/cpu/thread_context.hh | 24 ++++++++ 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(val); } + /** Records a CC register being set to a value. */ + void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + { + setResult(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 void setResult(T t) { @@ -252,6 +259,13 @@ class CheckerCPU : public BaseCPU setResult(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(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::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::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 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) { @@ -220,6 +229,14 @@ InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val) cpu->setFloatRegBits(reg_idx, val, tid); } +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::FullO3CPU(DerivO3CPUParams *params) commit(this, params), regFile(params->numPhysIntRegs, - params->numPhysFloatRegs), + params->numPhysFloatRegs, + params->numPhysCCRegs), freeList(name() + ".freelist", ®File), @@ -327,6 +328,7 @@ FullO3CPU::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::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::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::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::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::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::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 " @@ -1365,6 +1411,14 @@ FullO3CPU::readFloatRegBits(int reg_idx) return regFile.readFloatRegBits(reg_idx); } +template +CCReg +FullO3CPU::readCCReg(int reg_idx) +{ + ccRegfileReads++; + return regFile.readCCReg(reg_idx); +} + template void FullO3CPU::setIntReg(int reg_idx, uint64_t val) @@ -1389,6 +1443,14 @@ FullO3CPU::setFloatRegBits(int reg_idx, FloatRegBits val) regFile.setFloatRegBits(reg_idx, val); } +template +void +FullO3CPU::setCCReg(int reg_idx, CCReg val) +{ + ccRegfileWrites++; + regFile.setCCReg(reg_idx, val); +} + template uint64_t FullO3CPU::readArchIntReg(int reg_idx, ThreadID tid) @@ -1419,6 +1481,16 @@ FullO3CPU::readArchFloatRegInt(int reg_idx, ThreadID tid) return regFile.readFloatRegBits(phys_reg); } +template +CCReg +FullO3CPU::readArchCCReg(int reg_idx, ThreadID tid) +{ + ccRegfileReads++; + PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); + + return regFile.readCCReg(phys_reg); +} + template void FullO3CPU::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) @@ -1449,6 +1521,16 @@ FullO3CPU::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) regFile.setFloatRegBits(phys_reg, val); } +template +void +FullO3CPU::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) +{ + ccRegfileWrites++; + PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); + + regFile.setCCReg(phys_reg, val); +} + template TheISA::PCState FullO3CPU::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 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 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 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 BaseDynInst::setFloatRegOperandBits(si, idx, val); } + void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + { + this->cpu->setCCReg(this->_destRegIdx[idx], val); + BaseDynInst::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::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 floatRegFile; + /** Condition-code register file. */ + std::vector 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::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::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::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; @@ -213,6 +216,17 @@ class UnifiedRenameMap return info; } + /** + * 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. @@ -259,6 +273,17 @@ class UnifiedRenameMap return phys_reg; } + /** + * 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. @@ -301,6 +326,16 @@ class UnifiedRenameMap floatMap.setEntry(arch_reg, phys_reg); } + /** + * 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 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 @@ -205,6 +206,13 @@ O3ThreadContext::readFloatRegBitsFlat(int reg_idx) return cpu->readArchFloatRegInt(reg_idx, thread->threadId()); } +template +TheISA::CCReg +O3ThreadContext::readCCRegFlat(int reg_idx) +{ + return cpu->readArchCCReg(reg_idx, thread->threadId()); +} + template void O3ThreadContext::setIntRegFlat(int reg_idx, uint64_t val) @@ -232,6 +240,15 @@ O3ThreadContext::setFloatRegBitsFlat(int reg_idx, FloatRegBits val) conditionalSquash(); } +template +void +O3ThreadContext::setCCRegFlat(int reg_idx, TheISA::CCReg val) +{ + cpu->setArchCCReg(reg_idx, val, thread->threadId()); + + conditionalSquash(); +} + template void O3ThreadContext::pcState(const TheISA::PCState &val) @@ -264,6 +281,13 @@ O3ThreadContext::flattenFloatIndex(int reg) return cpu->isa[thread->threadId()]->flattenFloatIndex(reg); } +template +int +O3ThreadContext::flattenCCIndex(int reg) +{ + return cpu->isa[thread->threadId()]->flattenCCIndex(reg); +} + template void O3ThreadContext::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 @@ -768,6 +769,13 @@ OzoneCPU::OzoneTC::readFloatRegBits(int reg_idx) return thread->renameTable[idx]->readIntResult(); } +template +CCReg +OzoneCPU::OzoneTC::readCCReg(int reg_idx) +{ + return thread->renameTable[reg_idx]->readCCResult(); +} + template void OzoneCPU::OzoneTC::setIntReg(int reg_idx, uint64_t val) @@ -799,6 +807,17 @@ OzoneCPU::OzoneTC::setFloatRegBits(int reg_idx, FloatRegBits val) panic("Unimplemented!"); } +template +void +OzoneCPU::OzoneTC::setCCReg(int reg_idx, CCReg val) +{ + thread->renameTable[reg_idx]->setCCResult(val); + + if (!thread->noSquashFromTC) { + cpu->squashFromTC(); + } +} + template void OzoneCPU::OzoneTC::setPC(Addr 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); } }; /** @{ */ -- 2.30.2