diff options
Diffstat (limited to 'src/cpu/o3')
-rw-r--r-- | src/cpu/o3/O3CPU.py | 14 | ||||
-rw-r--r-- | src/cpu/o3/comm.hh | 25 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 143 | ||||
-rw-r--r-- | src/cpu/o3/cpu.hh | 89 | ||||
-rw-r--r-- | src/cpu/o3/dyn_inst.hh | 132 | ||||
-rw-r--r-- | src/cpu/o3/free_list.hh | 100 | ||||
-rw-r--r-- | src/cpu/o3/inst_queue_impl.hh | 5 | ||||
-rw-r--r-- | src/cpu/o3/regfile.cc | 120 | ||||
-rw-r--r-- | src/cpu/o3/regfile.hh | 161 | ||||
-rw-r--r-- | src/cpu/o3/rename.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/rename_impl.hh | 19 | ||||
-rw-r--r-- | src/cpu/o3/rename_map.cc | 91 | ||||
-rw-r--r-- | src/cpu/o3/rename_map.hh | 82 | ||||
-rwxr-xr-x | src/cpu/o3/thread_context.hh | 97 | ||||
-rwxr-xr-x | src/cpu/o3/thread_context_impl.hh | 42 |
15 files changed, 1085 insertions, 38 deletions
diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index cab2cf34f..8507ab6ff 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -1,3 +1,15 @@ +# Copyright (c) 2016 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2005-2007 The Regents of The University of Michigan # All rights reserved. # @@ -125,6 +137,8 @@ class DerivO3CPU(BaseCPU): # (it's a side effect of int reg renaming), so they should # never be the bottleneck here. _defaultNumPhysCCRegs = Self.numPhysIntRegs * 5 + numPhysVecRegs = Param.Unsigned(256, "Number of physical vector " + "registers") numPhysCCRegs = Param.Unsigned(_defaultNumPhysCCRegs, "Number of physical cc registers") numIQEntries = Param.Unsigned(64, "Number of instruction queue entries") diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index 49e153a52..f5be5a804 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -75,12 +75,18 @@ class PhysRegId : private RegId { : RegId(_regClass, _regIdx), flatIdx(_flatIdx) {} + /** Vector PhysRegId constructor (w/ elemIndex). */ + explicit PhysRegId(RegClass _regClass, PhysRegIndex _regIdx, + ElemIndex elem_idx, PhysRegIndex flat_idx) + : RegId(_regClass, _regIdx, elem_idx), flatIdx(flat_idx) { } + /** Visible RegId methods */ /** @{ */ using RegId::index; using RegId::classValue; using RegId::isZeroReg; using RegId::className; + using RegId::elemIndex; /** @} */ /** * Explicit forward methods, to prevent comparisons of PhysRegId with @@ -109,6 +115,12 @@ class PhysRegId : private RegId { /** @Return true if it is a condition-code physical register. */ bool isCCPhysReg() const { return isCCReg(); } + /** @Return true if it is a vector physical register. */ + bool isVectorPhysReg() const { return isVecReg(); } + + /** @Return true if it is a vector element physical register. */ + bool isVectorPhysElem() const { return isVecElem(); } + /** @Return true if it is a condition-code physical register. */ bool isMiscPhysReg() const { return isMiscReg(); } @@ -123,11 +135,18 @@ class PhysRegId : private RegId { /** Flat index accessor */ const PhysRegIndex& flatIndex() const { return flatIdx; } + + static PhysRegId elemId(const PhysRegId* vid, ElemIndex elem) + { + assert(vid->isVectorPhysReg()); + return PhysRegId(VecElemClass, vid->index(), elem); + } }; -// PhysRegIds only need to be created once and then we can use the following -// to work with them -typedef const PhysRegId* PhysRegIdPtr; +/** Constant pointer definition. + * PhysRegIds only need to be created once and then we can just share + * pointers */ +using PhysRegIdPtr = const PhysRegId*; /** Struct that defines the information passed from fetch to decode. */ template<class Impl> diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index a7a39b72a..c249d90ba 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014 ARM Limited + * Copyright (c) 2011-2012, 2014, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -46,6 +46,7 @@ #include "cpu/o3/cpu.hh" +#include "arch/generic/traits.hh" #include "arch/kernel_stats.hh" #include "config/the_isa.hh" #include "cpu/activity.hh" @@ -171,9 +172,14 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) iew(this, params), commit(this, params), + /* It is mandatory that all SMT threads use the same renaming mode as + * they are sharing registers and rename */ + vecMode(initRenameMode<TheISA::ISA>::mode(params->isa[0])), regFile(params->numPhysIntRegs, params->numPhysFloatRegs, - params->numPhysCCRegs), + params->numPhysVecRegs, + params->numPhysCCRegs, + vecMode), freeList(name() + ".freelist", ®File), @@ -270,6 +276,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->numPhysVecRegs >= numThreads * TheISA::NumVecRegs); assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); rename.setScoreboard(&scoreboard); @@ -278,6 +285,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) // Setup the rename map for whichever stages need it. for (ThreadID tid = 0; tid < numThreads; tid++) { isa[tid] = params->isa[tid]; + assert(initRenameMode<TheISA::ISA>::equals(isa[tid], isa[0])); // Only Alpha has an FP zero register, so for other ISAs we // use an invalid FP register index to avoid special treatment @@ -287,10 +295,11 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, - &freeList); + &freeList, + vecMode); renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, - &freeList); + &freeList, vecMode); } // Initialize rename map to assign physical registers to the @@ -311,6 +320,30 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) RegId(FloatRegClass, ridx), phys_reg); } + /* Here we need two 'interfaces' the 'whole register' and the + * 'register element'. At any point only one of them will be + * active. */ + if (vecMode == Enums::Full) { + /* Initialize the full-vector interface */ + for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) { + RegId rid = RegId(VecRegClass, ridx); + PhysRegIdPtr phys_reg = freeList.getVecReg(); + renameMap[tid].setEntry(rid, phys_reg); + commitRenameMap[tid].setEntry(rid, phys_reg); + } + } else { + /* Initialize the vector-element interface */ + for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) { + for (ElemIndex ldx = 0; ldx < TheISA::NumVecElemPerVecReg; + ++ldx) { + RegId lrid = RegId(VecElemClass, ridx, ldx); + PhysRegIdPtr phys_elem = freeList.getVecElem(); + renameMap[tid].setEntry(lrid, phys_elem); + commitRenameMap[tid].setEntry(lrid, phys_elem); + } + } + } + for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { PhysRegIdPtr phys_reg = freeList.getCCReg(); renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg); @@ -514,6 +547,16 @@ FullO3CPU<Impl>::regStats() .desc("number of floating regfile writes") .prereq(fpRegfileWrites); + vecRegfileReads + .name(name() + ".vec_regfile_reads") + .desc("number of vector regfile reads") + .prereq(vecRegfileReads); + + vecRegfileWrites + .name(name() + ".vec_regfile_writes") + .desc("number of vector regfile writes") + .prereq(vecRegfileWrites); + ccRegfileReads .name(name() + ".cc_regfile_reads") .desc("number of cc regfile reads") @@ -1257,6 +1300,32 @@ FullO3CPU<Impl>::readFloatRegBits(PhysRegIdPtr phys_reg) } template <class Impl> +auto +FullO3CPU<Impl>::readVecReg(PhysRegIdPtr phys_reg) const + -> const VecRegContainer& +{ + vecRegfileReads++; + return regFile.readVecReg(phys_reg); +} + +template <class Impl> +auto +FullO3CPU<Impl>::getWritableVecReg(PhysRegIdPtr phys_reg) + -> VecRegContainer& +{ + vecRegfileWrites++; + return regFile.getWritableVecReg(phys_reg); +} + +template <class Impl> +auto +FullO3CPU<Impl>::readVecElem(PhysRegIdPtr phys_reg) const -> const VecElem& +{ + vecRegfileReads++; + return regFile.readVecElem(phys_reg); +} + +template <class Impl> CCReg FullO3CPU<Impl>::readCCReg(PhysRegIdPtr phys_reg) { @@ -1290,6 +1359,22 @@ FullO3CPU<Impl>::setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val) template <class Impl> void +FullO3CPU<Impl>::setVecReg(PhysRegIdPtr phys_reg, const VecRegContainer& val) +{ + vecRegfileWrites++; + regFile.setVecReg(phys_reg, val); +} + +template <class Impl> +void +FullO3CPU<Impl>::setVecElem(PhysRegIdPtr phys_reg, const VecElem& val) +{ + vecRegfileWrites++; + regFile.setVecElem(phys_reg, val); +} + +template <class Impl> +void FullO3CPU<Impl>::setCCReg(PhysRegIdPtr phys_reg, CCReg val) { ccRegfileWrites++; @@ -1330,6 +1415,36 @@ FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) } template <class Impl> +auto +FullO3CPU<Impl>::readArchVecReg(int reg_idx, ThreadID tid) const + -> const VecRegContainer& +{ + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx)); + return readVecReg(phys_reg); +} + +template <class Impl> +auto +FullO3CPU<Impl>::getWritableArchVecReg(int reg_idx, ThreadID tid) + -> VecRegContainer& +{ + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx)); + return getWritableVecReg(phys_reg); +} + +template <class Impl> +auto +FullO3CPU<Impl>::readArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, + ThreadID tid) const -> const VecElem& +{ + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx, ldx)); + return readVecElem(phys_reg); +} + +template <class Impl> CCReg FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) { @@ -1375,6 +1490,26 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) template <class Impl> void +FullO3CPU<Impl>::setArchVecReg(int reg_idx, const VecRegContainer& val, + ThreadID tid) +{ + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx)); + setVecReg(phys_reg, val); +} + +template <class Impl> +void +FullO3CPU<Impl>::setArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, + const VecElem& val, ThreadID tid) +{ + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx, ldx)); + setVecElem(phys_reg, val); +} + +template <class Impl> +void FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) { ccRegfileWrites++; diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index b5cbc5fe2..d78d1b9d3 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 ARM Limited + * Copyright (c) 2011-2013, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -53,6 +53,7 @@ #include <set> #include <vector> +#include "arch/generic/types.hh" #include "arch/types.hh" #include "base/statistics.hh" #include "config/the_isa.hh" @@ -103,6 +104,9 @@ class FullO3CPU : public BaseO3CPU typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; + using VecElem = TheISA::VecElem; + using VecRegContainer = TheISA::VecRegContainer; + typedef O3ThreadState<Impl> ImplState; typedef O3ThreadState<Impl> Thread; @@ -417,6 +421,46 @@ class FullO3CPU : public BaseO3CPU TheISA::FloatRegBits readFloatRegBits(PhysRegIdPtr phys_reg); + const VecRegContainer& readVecReg(PhysRegIdPtr reg_idx) const; + + /** + * Read physical vector register for modification. + */ + VecRegContainer& getWritableVecReg(PhysRegIdPtr reg_idx); + + /** + * Read physical vector register lane + */ + template<typename VecElem, int LaneIdx> + VecLaneT<VecElem, true> + readVecLane(PhysRegIdPtr phys_reg) const + { + vecRegfileReads++; + return regFile.readVecLane<VecElem, LaneIdx>(phys_reg); + } + + /** + * Read physical vector register lane + */ + template<typename VecElem> + VecLaneT<VecElem, true> + readVecLane(PhysRegIdPtr phys_reg) const + { + vecRegfileReads++; + return regFile.readVecLane<VecElem>(phys_reg); + } + + /** Write a lane of the destination vector register. */ + template<typename LD> + void + setVecLane(PhysRegIdPtr phys_reg, const LD& val) + { + vecRegfileWrites++; + return regFile.setVecLane(phys_reg, val); + } + + const VecElem& readVecElem(PhysRegIdPtr reg_idx) const; + TheISA::CCReg readCCReg(PhysRegIdPtr phys_reg); void setIntReg(PhysRegIdPtr phys_reg, uint64_t val); @@ -425,6 +469,10 @@ class FullO3CPU : public BaseO3CPU void setFloatRegBits(PhysRegIdPtr phys_reg, TheISA::FloatRegBits val); + void setVecReg(PhysRegIdPtr reg_idx, const VecRegContainer& val); + + void setVecElem(PhysRegIdPtr reg_idx, const VecElem& val); + void setCCReg(PhysRegIdPtr phys_reg, TheISA::CCReg val); uint64_t readArchIntReg(int reg_idx, ThreadID tid); @@ -433,6 +481,34 @@ class FullO3CPU : public BaseO3CPU uint64_t readArchFloatRegInt(int reg_idx, ThreadID tid); + const VecRegContainer& readArchVecReg(int reg_idx, ThreadID tid) const; + /** Read architectural vector register for modification. */ + VecRegContainer& getWritableArchVecReg(int reg_idx, ThreadID tid); + + /** Read architectural vector register lane. */ + template<typename VecElem> + VecLaneT<VecElem, true> + readArchVecLane(int reg_idx, int lId, ThreadID tid) const + { + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx)); + return readVecLane<VecElem>(phys_reg); + } + + + /** Write a lane of the destination vector register. */ + template<typename LD> + void + setArchVecLane(int reg_idx, int lId, ThreadID tid, const LD& val) + { + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( + RegId(VecRegClass, reg_idx)); + setVecLane(phys_reg, val); + } + + const VecElem& readArchVecElem(const RegIndex& reg_idx, + const ElemIndex& ldx, ThreadID tid) const; + TheISA::CCReg readArchCCReg(int reg_idx, ThreadID tid); /** Architectural register accessors. Looks up in the commit @@ -446,6 +522,11 @@ class FullO3CPU : public BaseO3CPU void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid); + void setArchVecReg(int reg_idx, const VecRegContainer& val, ThreadID tid); + + void setArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, + const VecElem& val, ThreadID tid); + void setArchCCReg(int reg_idx, TheISA::CCReg val, ThreadID tid); /** Sets the commit PC state of a specific thread. */ @@ -540,6 +621,9 @@ class FullO3CPU : public BaseO3CPU /** The commit stage. */ typename CPUPolicy::Commit commit; + /** The rename mode of the vector registers */ + Enums::VecRegRenameMode vecMode; + /** The register file. */ PhysRegFile regFile; @@ -722,6 +806,9 @@ class FullO3CPU : public BaseO3CPU //number of float register file accesses Stats::Scalar fpRegfileReads; Stats::Scalar fpRegfileWrites; + //number of vector register file accesses + mutable Stats::Scalar vecRegfileReads; + Stats::Scalar vecRegfileWrites; //number of CC register file accesses Stats::Scalar ccRegfileReads; Stats::Scalar ccRegfileWrites; diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index a6adb4c20..0643e7e30 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -72,6 +72,9 @@ class BaseO3DynInst : public BaseDynInst<Impl> typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::CCReg CCReg; + using VecRegContainer = TheISA::VecRegContainer; + using VecElem = TheISA::VecElem; + static constexpr auto NumVecElemPerVecReg = TheISA::NumVecElemPerVecReg; /** Misc register type. */ typedef TheISA::MiscReg MiscReg; @@ -83,9 +86,9 @@ class BaseO3DynInst : public BaseDynInst<Impl> public: /** BaseDynInst constructor given a binary instruction. */ - BaseO3DynInst(const StaticInstPtr &staticInst, const StaticInstPtr ¯oop, - TheISA::PCState pc, TheISA::PCState predPC, - InstSeqNum seq_num, O3CPU *cpu); + BaseO3DynInst(const StaticInstPtr &staticInst, const StaticInstPtr + ¯oop, TheISA::PCState pc, TheISA::PCState predPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ BaseO3DynInst(const StaticInstPtr &_staticInst, @@ -107,6 +110,11 @@ class BaseO3DynInst : public BaseDynInst<Impl> void initVars(); protected: + /** Explicitation of dependent names. */ + using BaseDynInst<Impl>::cpu; + using BaseDynInst<Impl>::_srcRegIdx; + using BaseDynInst<Impl>::_destRegIdx; + /** Values to be written to the destination misc. registers. */ std::array<MiscReg, TheISA::MaxMiscDestRegs> _destMiscRegVal; @@ -213,19 +221,30 @@ class BaseO3DynInst : public BaseDynInst<Impl> switch (original_dest_reg.classValue()) { case IntRegClass: this->setIntRegOperand(this->staticInst.get(), idx, - this->cpu->readIntReg(prev_phys_reg)); + this->cpu->readIntReg(prev_phys_reg)); break; case FloatRegClass: this->setFloatRegOperandBits(this->staticInst.get(), idx, - this->cpu->readFloatRegBits(prev_phys_reg)); + this->cpu->readFloatRegBits(prev_phys_reg)); + break; + case VecRegClass: + this->setVecRegOperand(this->staticInst.get(), idx, + this->cpu->readVecReg(prev_phys_reg)); + break; + case VecElemClass: + this->setVecElemOperand(this->staticInst.get(), idx, + this->cpu->readVecElem(prev_phys_reg)); break; case CCRegClass: this->setCCRegOperand(this->staticInst.get(), idx, - this->cpu->readCCReg(prev_phys_reg)); + this->cpu->readCCReg(prev_phys_reg)); break; case MiscRegClass: // no need to forward misc reg values break; + default: + panic("Unknown register class: %d", + (int)original_dest_reg.classValue()); } } } @@ -266,6 +285,89 @@ class BaseO3DynInst : public BaseDynInst<Impl> return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } + const VecRegContainer& + readVecRegOperand(const StaticInst *si, int idx) const + { + return this->cpu->readVecReg(this->_srcRegIdx[idx]); + } + + /** + * Read destination vector register operand for modification. + */ + VecRegContainer& + getWritableVecRegOperand(const StaticInst *si, int idx) + { + return this->cpu->getWritableVecReg(this->_destRegIdx[idx]); + } + + /** Vector Register Lane Interfaces. */ + /** @{ */ + /** Reads source vector 8bit operand. */ + ConstVecLane8 + readVec8BitLaneOperand(const StaticInst *si, int idx) const + { + return cpu->template readVecLane<uint8_t>(_srcRegIdx[idx]); + } + + /** Reads source vector 16bit operand. */ + ConstVecLane16 + readVec16BitLaneOperand(const StaticInst *si, int idx) const + { + return cpu->template readVecLane<uint16_t>(_srcRegIdx[idx]); + } + + /** Reads source vector 32bit operand. */ + ConstVecLane32 + readVec32BitLaneOperand(const StaticInst *si, int idx) const + { + return cpu->template readVecLane<uint32_t>(_srcRegIdx[idx]); + } + + /** Reads source vector 64bit operand. */ + ConstVecLane64 + readVec64BitLaneOperand(const StaticInst *si, int idx) const + { + return cpu->template readVecLane<uint64_t>(_srcRegIdx[idx]); + } + + /** Write a lane of the destination vector operand. */ + template <typename LD> + void + setVecLaneOperandT(const StaticInst *si, int idx, const LD& val) + { + return cpu->template setVecLane(_destRegIdx[idx], val); + } + virtual void + setVecLaneOperand(const StaticInst *si, int idx, + const LaneData<LaneSize::Byte>& val) + { + return setVecLaneOperandT(si, idx, val); + } + virtual void + setVecLaneOperand(const StaticInst *si, int idx, + const LaneData<LaneSize::TwoByte>& val) + { + return setVecLaneOperandT(si, idx, val); + } + virtual void + setVecLaneOperand(const StaticInst *si, int idx, + const LaneData<LaneSize::FourByte>& val) + { + return setVecLaneOperandT(si, idx, val); + } + virtual void + setVecLaneOperand(const StaticInst *si, int idx, + const LaneData<LaneSize::EightByte>& val) + { + return setVecLaneOperandT(si, idx, val); + } + /** @} */ + + VecElem readVecElemOperand(const StaticInst *si, int idx) const + { + return this->cpu->readVecElem(this->_srcRegIdx[idx]); + } + CCReg readCCRegOperand(const StaticInst *si, int idx) { return this->cpu->readCCReg(this->_srcRegIdx[idx]); @@ -293,6 +395,22 @@ class BaseO3DynInst : public BaseDynInst<Impl> BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } + void + setVecRegOperand(const StaticInst *si, int idx, + const VecRegContainer& val) + { + this->cpu->setVecReg(this->_destRegIdx[idx], val); + BaseDynInst<Impl>::setVecRegOperand(si, idx, val); + } + + void setVecElemOperand(const StaticInst *si, int idx, + const VecElem val) + { + int reg_idx = idx; + this->cpu->setVecElem(this->_destRegIdx[reg_idx], val); + BaseDynInst<Impl>::setVecElemOperand(si, idx, val); + } + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { this->cpu->setCCReg(this->_destRegIdx[idx], val); diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh index 6fc6cc909..f4c26a697 100644 --- a/src/cpu/o3/free_list.hh +++ b/src/cpu/o3/free_list.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2016 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. @@ -63,6 +75,16 @@ class SimpleFreeList /** Add a physical register to the free list */ void addReg(PhysRegIdPtr reg) { freeRegs.push(reg); } + /** Add physical registers to the free list */ + template<class InputIt> + void + addRegs(InputIt first, InputIt last) { + std::for_each(first, last, + [this](const typename InputIt::value_type& reg) { + this->freeRegs.push(®); + }); + } + /** Get the next available register from the free list */ PhysRegIdPtr getReg() { @@ -107,6 +129,15 @@ class UnifiedFreeList /** The list of free floating point registers. */ SimpleFreeList floatList; + /** The following two are exclusive interfaces. */ + /** @{ */ + /** The list of free vector registers. */ + SimpleFreeList vecList; + + /** The list of free vector element registers. */ + SimpleFreeList vecElemList; + /** @} */ + /** The list of free condition-code registers. */ SimpleFreeList ccList; @@ -146,18 +177,36 @@ class UnifiedFreeList /** Gets a free fp register. */ PhysRegIdPtr getFloatReg() { return floatList.getReg(); } + /** Gets a free vector register. */ + PhysRegIdPtr getVecReg() { return vecList.getReg(); } + + /** Gets a free vector elemenet register. */ + PhysRegIdPtr getVecElem() { return vecElemList.getReg(); } + /** Gets a free cc register. */ PhysRegIdPtr getCCReg() { return ccList.getReg(); } /** Adds a register back to the free list. */ void addReg(PhysRegIdPtr freed_reg); + /** Adds a register back to the free list. */ + template<class InputIt> + void addRegs(InputIt first, InputIt last); + /** Adds an integer register back to the free list. */ void addIntReg(PhysRegIdPtr freed_reg) { intList.addReg(freed_reg); } /** Adds a fp register back to the free list. */ void addFloatReg(PhysRegIdPtr freed_reg) { floatList.addReg(freed_reg); } + /** Adds a vector register back to the free list. */ + void addVecReg(PhysRegIdPtr freed_reg) { vecList.addReg(freed_reg); } + + /** Adds a vector element register back to the free list. */ + void addVecElem(PhysRegIdPtr freed_reg) { + vecElemList.addReg(freed_reg); + } + /** Adds a cc register back to the free list. */ void addCCReg(PhysRegIdPtr freed_reg) { ccList.addReg(freed_reg); } @@ -167,6 +216,12 @@ class UnifiedFreeList /** Checks if there are any free fp registers. */ bool hasFreeFloatRegs() const { return floatList.hasFreeRegs(); } + /** Checks if there are any free vector registers. */ + bool hasFreeVecRegs() const { return vecList.hasFreeRegs(); } + + /** Checks if there are any free vector registers. */ + bool hasFreeVecElems() const { return vecElemList.hasFreeRegs(); } + /** Checks if there are any free cc registers. */ bool hasFreeCCRegs() const { return ccList.hasFreeRegs(); } @@ -176,10 +231,49 @@ class UnifiedFreeList /** Returns the number of free fp registers. */ unsigned numFreeFloatRegs() const { return floatList.numFreeRegs(); } + /** Returns the number of free vector registers. */ + unsigned numFreeVecRegs() const { return vecList.numFreeRegs(); } + /** Returns the number of free cc registers. */ unsigned numFreeCCRegs() const { return ccList.numFreeRegs(); } }; +template<class InputIt> +inline void +UnifiedFreeList::addRegs(InputIt first, InputIt last) +{ + // Are there any registers to add? + if (first == last) + return; + + panic_if((first != last) && + first->classValue() != (last-1)->classValue(), + "Attempt to add mixed type regs: %s and %s", + first->className(), + (last-1)->className()); + switch (first->classValue()) { + case IntRegClass: + intList.addRegs(first, last); + break; + case FloatRegClass: + floatList.addRegs(first, last); + break; + case VecRegClass: + vecList.addRegs(first, last); + break; + case VecElemClass: + vecElemList.addRegs(first, last); + break; + case CCRegClass: + ccList.addRegs(first, last); + break; + default: + panic("Unexpected RegClass (%s)", + first->className()); + } + +} + inline void UnifiedFreeList::addReg(PhysRegIdPtr freed_reg) { @@ -194,6 +288,12 @@ UnifiedFreeList::addReg(PhysRegIdPtr freed_reg) case FloatRegClass: floatList.addReg(freed_reg); break; + case VecRegClass: + vecList.addReg(freed_reg); + break; + case VecElemClass: + vecElemList.addReg(freed_reg); + break; case CCRegClass: ccList.addReg(freed_reg); break; diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index f52cf2d6c..2b113ae04 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -98,8 +98,11 @@ InstructionQueue<Impl>::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, numThreads = params->numThreads; // Set the number of total physical registers + // As the vector registers have two addressing modes, they are added twice numPhysRegs = params->numPhysIntRegs + params->numPhysFloatRegs + - params->numPhysCCRegs; + params->numPhysVecRegs + + params->numPhysVecRegs * TheISA::NumVecElemPerVecReg + + 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 ea4370f48..2f41e2ac2 100644 --- a/src/cpu/o3/regfile.cc +++ b/src/cpu/o3/regfile.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2016 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. @@ -34,19 +46,30 @@ #include "cpu/o3/regfile.hh" #include "cpu/o3/free_list.hh" +#include "arch/generic/types.hh" +#include "cpu/o3/free_list.hh" PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, unsigned _numPhysicalFloatRegs, - unsigned _numPhysicalCCRegs) + unsigned _numPhysicalVecRegs, + unsigned _numPhysicalCCRegs, + VecMode vmode) : intRegFile(_numPhysicalIntRegs), floatRegFile(_numPhysicalFloatRegs), + vectorRegFile(_numPhysicalVecRegs), ccRegFile(_numPhysicalCCRegs), numPhysicalIntRegs(_numPhysicalIntRegs), numPhysicalFloatRegs(_numPhysicalFloatRegs), + numPhysicalVecRegs(_numPhysicalVecRegs), + numPhysicalVecElemRegs(_numPhysicalVecRegs * + NumVecElemPerVecReg), numPhysicalCCRegs(_numPhysicalCCRegs), totalNumRegs(_numPhysicalIntRegs + _numPhysicalFloatRegs - + _numPhysicalCCRegs) + + _numPhysicalVecRegs + + _numPhysicalVecRegs * NumVecElemPerVecReg + + _numPhysicalCCRegs), + vecMode(vmode) { PhysRegIndex phys_reg; PhysRegIndex flat_reg_idx = 0; @@ -68,6 +91,23 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, floatRegIds.emplace_back(FloatRegClass, phys_reg, flat_reg_idx++); } + // The next batch of the registers are the vector physical + // registers; put them onto the vector free list. + for (phys_reg = 0; phys_reg < numPhysicalVecRegs; phys_reg++) { + vectorRegFile[phys_reg].zero(); + vecRegIds.emplace_back(VecRegClass, phys_reg, flat_reg_idx++); + } + // The next batch of the registers are the vector element physical + // registers; they refer to the same containers as the vector + // registers, just a different (and incompatible) way to access + // them; put them onto the vector free list. + for (phys_reg = 0; phys_reg < numPhysicalVecRegs; phys_reg++) { + for (ElemIndex eIdx = 0; eIdx < NumVecElemPerVecReg; eIdx++) { + vecElemIds.emplace_back(VecElemClass, phys_reg, + eIdx, flat_reg_idx++); + } + } + // The rest of the registers are the condition-code physical // registers; put them onto the condition-code free list. for (phys_reg = 0; phys_reg < numPhysicalCCRegs; phys_reg++) { @@ -90,20 +130,90 @@ PhysRegFile::initFreeList(UnifiedFreeList *freeList) // The initial batch of registers are the integer ones for (reg_idx = 0; reg_idx < numPhysicalIntRegs; reg_idx++) { assert(intRegIds[reg_idx].index() == reg_idx); - freeList->addIntReg(&intRegIds[reg_idx]); } + freeList->addRegs(intRegIds.begin(), intRegIds.end()); // The next batch of the registers are the floating-point physical // registers; put them onto the floating-point free list. for (reg_idx = 0; reg_idx < numPhysicalFloatRegs; reg_idx++) { assert(floatRegIds[reg_idx].index() == reg_idx); - freeList->addFloatReg(&floatRegIds[reg_idx]); } + freeList->addRegs(floatRegIds.begin(), floatRegIds.end()); + + /* The next batch of the registers are the vector physical + * registers; put them onto the vector free list. */ + for (reg_idx = 0; reg_idx < numPhysicalVecRegs; reg_idx++) { + assert(vecRegIds[reg_idx].index() == reg_idx); + for (ElemIndex elemIdx = 0; elemIdx < NumVecElemPerVecReg; elemIdx++) { + assert(vecElemIds[reg_idx * NumVecElemPerVecReg + + elemIdx].index() == reg_idx); + assert(vecElemIds[reg_idx * NumVecElemPerVecReg + + elemIdx].elemIndex() == elemIdx); + } + } + + /* depending on the mode we add the vector registers as whole units or + * as different elements. */ + if (vecMode == Enums::Full) + freeList->addRegs(vecRegIds.begin(), vecRegIds.end()); + else + freeList->addRegs(vecElemIds.begin(), vecElemIds.end()); // The rest of the registers are the condition-code physical // registers; put them onto the condition-code free list. for (reg_idx = 0; reg_idx < numPhysicalCCRegs; reg_idx++) { assert(ccRegIds[reg_idx].index() == reg_idx); - freeList->addCCReg(&ccRegIds[reg_idx]); } + freeList->addRegs(ccRegIds.begin(), ccRegIds.end()); } + +auto +PhysRegFile::getRegElemIds(PhysRegIdPtr reg) -> IdRange +{ + panic_if(!reg->isVectorPhysReg(), + "Trying to get elems of a %s register", reg->className()); + auto idx = reg->index(); + return std::make_pair( + vecElemIds.begin() + idx * NumVecElemPerVecReg, + vecElemIds.begin() + (idx+1) * NumVecElemPerVecReg); +} + +auto +PhysRegFile::getRegIds(RegClass cls) -> IdRange +{ + switch (cls) + { + case IntRegClass: + return std::make_pair(intRegIds.begin(), intRegIds.end()); + case FloatRegClass: + return std::make_pair(floatRegIds.begin(), floatRegIds.end()); + case VecRegClass: + return std::make_pair(vecRegIds.begin(), vecRegIds.end()); + case VecElemClass: + return std::make_pair(vecElemIds.begin(), vecElemIds.end()); + case CCRegClass: + return std::make_pair(ccRegIds.begin(), ccRegIds.end()); + case MiscRegClass: + return std::make_pair(miscRegIds.begin(), miscRegIds.end()); + } + /* There is no way to make an empty iterator */ + return std::make_pair(PhysIds::const_iterator(), + PhysIds::const_iterator()); +} + +PhysRegIdPtr +PhysRegFile::getTrueId(PhysRegIdPtr reg) +{ + switch (reg->classValue()) { + case VecRegClass: + return &vecRegIds[reg->index()]; + case VecElemClass: + return &vecElemIds[reg->index() * NumVecElemPerVecReg + + reg->elemIndex()]; + default: + panic_if(!reg->isVectorPhysElem(), + "Trying to get the register of a %s register", reg->className()); + } + return nullptr; +} + diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index c353b2746..7feec933f 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2016 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. @@ -42,6 +54,7 @@ #include "config/the_isa.hh" #include "cpu/o3/comm.hh" #include "debug/IEW.hh" +#include "enums/VecRegRenameMode.hh" class UnifiedFreeList; @@ -56,6 +69,15 @@ class PhysRegFile typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::CCReg CCReg; + using VecElem = TheISA::VecElem; + using VecRegContainer = TheISA::VecRegContainer; + using PhysIds = std::vector<PhysRegId>; + using VecMode = Enums::VecRegRenameMode; + public: + using IdRange = std::pair<PhysIds::const_iterator, + PhysIds::const_iterator>; + private: + static constexpr auto NumVecElemPerVecReg = TheISA::NumVecElemPerVecReg; typedef union { FloatReg d; @@ -70,6 +92,11 @@ class PhysRegFile std::vector<PhysFloatReg> floatRegFile; std::vector<PhysRegId> floatRegIds; + /** Vector register file. */ + std::vector<VecRegContainer> vectorRegFile; + std::vector<PhysRegId> vecRegIds; + std::vector<PhysRegId> vecElemIds; + /** Condition-code register file. */ std::vector<CCReg> ccRegFile; std::vector<PhysRegId> ccRegIds; @@ -83,18 +110,31 @@ class PhysRegFile unsigned numPhysicalIntRegs; /** - * Number of physical general purpose registers + * Number of physical floating point registers */ unsigned numPhysicalFloatRegs; /** - * Number of physical general purpose registers + * Number of physical vector registers + */ + unsigned numPhysicalVecRegs; + + /** + * Number of physical vector element registers + */ + unsigned numPhysicalVecElemRegs; + + /** + * Number of physical CC registers */ unsigned numPhysicalCCRegs; /** Total number of physical registers. */ unsigned totalNumRegs; + /** Mode in which vector registers are addressed. */ + VecMode vecMode; + public: /** * Constructs a physical register file with the specified amount of @@ -102,7 +142,10 @@ class PhysRegFile */ PhysRegFile(unsigned _numPhysicalIntRegs, unsigned _numPhysicalFloatRegs, - unsigned _numPhysicalCCRegs); + unsigned _numPhysicalVecRegs, + unsigned _numPhysicalCCRegs, + VecMode vmode + ); /** * Destructor to free resources @@ -117,6 +160,11 @@ class PhysRegFile /** @return the number of floating-point physical registers. */ unsigned numFloatPhysRegs() const { return numPhysicalFloatRegs; } + /** @return the number of vector physical registers. */ + unsigned numVecPhysRegs() const { return numPhysicalVecRegs; } + + /** @return the number of vector physical registers. */ + unsigned numVecElemPhysRegs() const { return numPhysicalVecElemRegs; } /** @return the number of condition-code physical registers. */ unsigned numCCPhysRegs() const { return numPhysicalCCRegs; } @@ -164,6 +212,68 @@ class PhysRegFile return floatRegBits; } + /** Reads a vector register. */ + const VecRegContainer& readVecReg(PhysRegIdPtr phys_reg) const + { + assert(phys_reg->isVectorPhysReg()); + + DPRINTF(IEW, "RegFile: Access to vector register %i, has " + "data %s\n", int(phys_reg->index()), + vectorRegFile[phys_reg->index()].as<VecElem>().print()); + + return vectorRegFile[phys_reg->index()]; + } + + /** Reads a vector register for modification. */ + VecRegContainer& getWritableVecReg(PhysRegIdPtr phys_reg) + { + /* const_cast for not duplicating code above. */ + return const_cast<VecRegContainer&>(readVecReg(phys_reg)); + } + + /** Reads a vector register lane. */ + template <typename VecElem, int LaneIdx> + VecLaneT<VecElem, true> + readVecLane(PhysRegIdPtr phys_reg) const + { + return readVecReg(phys_reg).laneView<VecElem, LaneIdx>(); + } + + /** Reads a vector register lane. */ + template <typename VecElem> + VecLaneT<VecElem, true> + readVecLane(PhysRegIdPtr phys_reg) const + { + return readVecReg(phys_reg).laneView<VecElem>(phys_reg->elemIndex()); + } + + /** Get a vector register lane for modification. */ + template <typename LD> + void + setVecLane(PhysRegIdPtr phys_reg, const LD& val) + { + assert(phys_reg->isVectorPhysReg()); + + DPRINTF(IEW, "RegFile: Setting vector register %i[%d] to %lx\n", + int(phys_reg->index()), phys_reg->elemIndex(), val); + + vectorRegFile[phys_reg->index()].laneView<typename LD::UnderlyingType>( + phys_reg->elemIndex()) = val; + } + + /** Reads a vector element. */ + const VecElem& readVecElem(PhysRegIdPtr phys_reg) const + { + assert(phys_reg->isVectorPhysElem()); + auto ret = vectorRegFile[phys_reg->index()].as<VecElem>(); + const VecElem& val = ret[phys_reg->elemIndex()]; + DPRINTF(IEW, "RegFile: Access to element %d of vector register %i," + " has data %#x\n", phys_reg->elemIndex(), + int(phys_reg->index()), val); + + return val; + } + /** Reads a condition-code register. */ CCReg readCCReg(PhysRegIdPtr phys_reg) { @@ -207,7 +317,31 @@ class PhysRegFile DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", phys_reg->index(), (uint64_t)val); - floatRegFile[phys_reg->index()].q = val; + if (!phys_reg->isZeroReg()) + floatRegFile[phys_reg->index()].q = val; + } + + /** Sets a vector register to the given value. */ + void setVecReg(PhysRegIdPtr phys_reg, const VecRegContainer& val) + { + assert(phys_reg->isVectorPhysReg()); + + DPRINTF(IEW, "RegFile: Setting vector register %i to %s\n", + int(phys_reg->index()), val.print()); + + vectorRegFile[phys_reg->index()] = val; + } + + /** Sets a vector register to the given value. */ + void setVecElem(PhysRegIdPtr phys_reg, const VecElem val) + { + assert(phys_reg->isVectorPhysElem()); + + DPRINTF(IEW, "RegFile: Setting element %d of vector register %i to" + " %#x\n", phys_reg->elemIndex(), int(phys_reg->index()), val); + + vectorRegFile[phys_reg->index()].as<VecElem>()[phys_reg->elemIndex()] = + val; } /** Sets a condition-code register to the given value. */ @@ -220,6 +354,25 @@ class PhysRegFile ccRegFile[phys_reg->index()] = val; } + + /** Get the PhysRegIds of the elems of a vector register. + * Auxiliary function to transition from Full vector mode to Elem mode. + */ + IdRange getRegElemIds(PhysRegIdPtr reg); + + /** + * Get the PhysRegIds of the elems of all vector registers. + * Auxiliary function to transition from Full vector mode to Elem mode + * and to initialise the rename map. + */ + IdRange getRegIds(RegClass cls); + + /** + * Get the true physical register id. + * As many parts work with PhysRegIdPtr, we need to be able to produce + * the pointer out of just class and register idx. + */ + PhysRegIdPtr getTrueId(PhysRegIdPtr reg); }; diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 6d3861ba6..d0f6ba13d 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -464,8 +464,6 @@ class DefaultRename /** The maximum skid buffer size. */ unsigned skidBufferMax; - PhysRegIndex maxPhysicalRegs; - /** Enum to record the source of a structure full stall. Can come from * either ROB, IQ, LSQ, and it is priortized in that order. */ @@ -515,6 +513,7 @@ class DefaultRename Stats::Scalar renameRenameLookups; Stats::Scalar intRenameLookups; Stats::Scalar fpRenameLookups; + Stats::Scalar vecRenameLookups; /** Stat for total number of committed renaming mappings. */ Stats::Scalar renameCommittedMaps; /** Stat for total number of mappings that were undone due to a squash. */ diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 9c9b030f5..b9adcdff7 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -67,9 +67,7 @@ DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params) commitToRenameDelay(params->commitToRenameDelay), renameWidth(params->renameWidth), commitWidth(params->commitWidth), - numThreads(params->numThreads), - maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs - + params->numPhysCCRegs) + numThreads(params->numThreads) { if (renameWidth > Impl::MaxWidth) fatal("renameWidth (%d) is larger than compiled limit (%d),\n" @@ -182,6 +180,10 @@ DefaultRename<Impl>::regStats() .name(name() + ".fp_rename_lookups") .desc("Number of floating rename lookups") .prereq(fpRenameLookups); + vecRenameLookups + .name(name() + ".vec_rename_lookups") + .desc("Number of vector rename lookups") + .prereq(vecRenameLookups); } template <class Impl> @@ -645,6 +647,8 @@ DefaultRename<Impl>::renameInsts(ThreadID tid) // to rename to. Otherwise block. if (!renameMap[tid]->canRename(inst->numIntDestRegs(), inst->numFPDestRegs(), + inst->numVecDestRegs(), + inst->numVecElemDestRegs(), inst->numCCDestRegs())) { DPRINTF(Rename, "Blocking due to lack of free " "physical registers to rename to.\n"); @@ -1239,12 +1243,17 @@ DefaultRename<Impl>::readFreeEntries(ThreadID tid) } DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, " - "Free LQ: %i, Free SQ: %i\n", + "Free LQ: %i, Free SQ: %i, FreeRM %i(%i %i %i %i)\n", tid, freeEntries[tid].iqEntries, freeEntries[tid].robEntries, freeEntries[tid].lqEntries, - freeEntries[tid].sqEntries); + freeEntries[tid].sqEntries, + renameMap[tid]->numFreeEntries(), + renameMap[tid]->numFreeIntEntries(), + renameMap[tid]->numFreeFloatEntries(), + renameMap[tid]->numFreeVecEntries(), + renameMap[tid]->numFreeCCEntries()); DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n", tid, instsInProgress[tid]); diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc index 38ccc7ec9..bde2a6921 100644 --- a/src/cpu/o3/rename_map.cc +++ b/src/cpu/o3/rename_map.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2016 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. @@ -93,15 +105,92 @@ void UnifiedRenameMap::init(PhysRegFile *_regFile, RegIndex _intZeroReg, RegIndex _floatZeroReg, - UnifiedFreeList *freeList) + UnifiedFreeList *freeList, + VecMode _mode) { regFile = _regFile; + vecMode = _mode; intMap.init(TheISA::NumIntRegs, &(freeList->intList), _intZeroReg); floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg); + vecMap.init(TheISA::NumVecRegs, &(freeList->vecList), (RegIndex)-1); + + vecElemMap.init(TheISA::NumVecRegs * NVecElems, + &(freeList->vecElemList), (RegIndex)-1); + ccMap.init(TheISA::NumCCRegs, &(freeList->ccList), (RegIndex)-1); } +void +UnifiedRenameMap::switchMode(VecMode newVecMode, UnifiedFreeList* freeList) +{ + if (newVecMode == Enums::Elem && vecMode == Enums::Full) { + /* Switch to vector element rename mode. */ + /* The free list should currently be tracking full registers. */ + panic_if(freeList->hasFreeVecElems(), + "The free list is already tracking Vec elems"); + panic_if(freeList->numFreeVecRegs() != + regFile->numVecPhysRegs() - TheISA::NumVecRegs, + "The free list has lost vector registers"); + /* Split the mapping of each arch reg. */ + int reg = 0; + for (auto &e: vecMap) { + PhysRegFile::IdRange range = this->regFile->getRegElemIds(e); + uint32_t i; + for (i = 0; range.first != range.second; i++, range.first++) { + vecElemMap.setEntry(RegId(VecElemClass, reg, i), + &(*range.first)); + } + panic_if(i != NVecElems, + "Wrong name of elems: expecting %u, got %d\n", + TheISA::NumVecElemPerVecReg, i); + reg++; + } + /* Split the free regs. */ + while (freeList->hasFreeVecRegs()) { + auto vr = freeList->getVecReg(); + auto range = this->regFile->getRegElemIds(vr); + freeList->addRegs(range.first, range.second); + } + vecMode = Enums::Elem; + } else if (newVecMode == Enums::Full && vecMode == Enums::Elem) { + /* Switch to full vector register rename mode. */ + /* The free list should currently be tracking register elems. */ + panic_if(freeList->hasFreeVecRegs(), + "The free list is already tracking full Vec"); + panic_if(freeList->numFreeVecRegs() != + regFile->numVecElemPhysRegs() - TheISA::NumFloatRegs, + "The free list has lost vector register elements"); + /* To rebuild the arch regs we take the easy road: + * 1.- Stitch the elems together into vectors. + * 2.- Replace the contents of the register file with the vectors + * 3.- Set the remaining registers as free + */ + TheISA::VecRegContainer new_RF[TheISA::NumVecRegs]; + for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) { + VecReg dst = new_RF[i].as<TheISA::VecElem>(); + for (uint32_t l = 0; l < NVecElems; l++) { + RegId s_rid(VecElemClass, i, l); + PhysRegIdPtr s_prid = vecElemMap.lookup(s_rid); + dst[l] = regFile->readVecElem(s_prid); + } + } + + for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) { + PhysRegId pregId(VecRegClass, i, 0); + regFile->setVecReg(regFile->getTrueId(&pregId), new_RF[i]); + } + + auto range = regFile->getRegIds(VecRegClass); + freeList->addRegs(range.first + TheISA::NumVecRegs, range.second); + + /* We remove the elems from the free list. */ + while (freeList->hasFreeVecElems()) + freeList->getVecElem(); + vecMode = Enums::Full; + } +} + diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh index 028c32e3a..ab909f090 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -54,6 +54,7 @@ #include "cpu/o3/free_list.hh" #include "cpu/o3/regfile.hh" #include "cpu/reg_class.hh" +#include "enums/VecRegRenameMode.hh" /** * Register rename map for a single class of registers (e.g., integer @@ -68,6 +69,10 @@ class SimpleRenameMap using Arch2PhysMap = std::vector<PhysRegIdPtr>; /** The acutal arch-to-phys register map */ Arch2PhysMap map; + public: + using iterator = Arch2PhysMap::iterator; + using const_iterator = Arch2PhysMap::const_iterator; + private: /** * Pointer to the free list from which new physical registers @@ -139,6 +144,20 @@ class SimpleRenameMap /** Return the number of free entries on the associated free list. */ unsigned numFreeEntries() const { return freeList->numFreeRegs(); } + + /** Forward begin/cbegin to the map. */ + /** @{ */ + iterator begin() { return map.begin(); } + const_iterator begin() const { return map.begin(); } + const_iterator cbegin() const { return map.cbegin(); } + /** @} */ + + /** Forward end/cend to the map. */ + /** @{ */ + iterator end() { return map.end(); } + const_iterator end() const { return map.end(); } + const_iterator cend() const { return map.cend(); } + /** @} */ }; @@ -152,6 +171,8 @@ class SimpleRenameMap class UnifiedRenameMap { private: + static constexpr uint32_t NVecElems = TheISA::NumVecElemPerVecReg; + using VecReg = TheISA::VecReg; /** The integer register rename map */ SimpleRenameMap intMap; @@ -162,6 +183,15 @@ class UnifiedRenameMap /** The condition-code register rename map */ SimpleRenameMap ccMap; + /** The vector register rename map */ + SimpleRenameMap vecMap; + + /** The vector element register rename map */ + SimpleRenameMap vecElemMap; + + using VecMode = Enums::VecRegRenameMode; + VecMode vecMode; + /** * The register file object is used only to get PhysRegIdPtr * on MiscRegs, as they are stored in it. @@ -182,7 +212,8 @@ class UnifiedRenameMap void init(PhysRegFile *_regFile, RegIndex _intZeroReg, RegIndex _floatZeroReg, - UnifiedFreeList *freeList); + UnifiedFreeList *freeList, + VecMode _mode); /** * Tell rename map to get a new free physical register to remap @@ -199,6 +230,12 @@ class UnifiedRenameMap return intMap.rename(arch_reg); case FloatRegClass: return floatMap.rename(arch_reg); + case VecRegClass: + assert(vecMode == Enums::Full); + return vecMap.rename(arch_reg); + case VecElemClass: + assert(vecMode == Enums::Elem); + return vecElemMap.rename(arch_reg); case CCRegClass: return ccMap.rename(arch_reg); case MiscRegClass: @@ -232,6 +269,14 @@ class UnifiedRenameMap case FloatRegClass: return floatMap.lookup(arch_reg); + case VecRegClass: + assert(vecMode == Enums::Full); + return vecMap.lookup(arch_reg); + + case VecElemClass: + assert(vecMode == Enums::Elem); + return vecElemMap.lookup(arch_reg); + case CCRegClass: return ccMap.lookup(arch_reg); @@ -265,6 +310,16 @@ class UnifiedRenameMap assert(phys_reg->isFloatPhysReg()); return floatMap.setEntry(arch_reg, phys_reg); + case VecRegClass: + assert(phys_reg->isVectorPhysReg()); + assert(vecMode == Enums::Full); + return vecMap.setEntry(arch_reg, phys_reg); + + case VecElemClass: + assert(phys_reg->isVectorPhysElem()); + assert(vecMode == Enums::Elem); + return vecElemMap.setEntry(arch_reg, phys_reg); + case CCRegClass: assert(phys_reg->isCCPhysReg()); return ccMap.setEntry(arch_reg, phys_reg); @@ -291,18 +346,39 @@ class UnifiedRenameMap */ unsigned numFreeEntries() const { - return std::min(intMap.numFreeEntries(), floatMap.numFreeEntries()); + return std::min( + std::min(intMap.numFreeEntries(), floatMap.numFreeEntries()), + vecMode == Enums::Full ? vecMap.numFreeEntries() + : vecElemMap.numFreeEntries()); } + unsigned numFreeIntEntries() const { return intMap.numFreeEntries(); } + unsigned numFreeFloatEntries() const { return floatMap.numFreeEntries(); } + unsigned numFreeVecEntries() const + { + return vecMode == Enums::Full + ? vecMap.numFreeEntries() + : vecElemMap.numFreeEntries(); + } + unsigned numFreeCCEntries() const { return ccMap.numFreeEntries(); } + /** * Return whether there are enough registers to serve the request. */ - bool canRename(uint32_t intRegs, uint32_t floatRegs, uint32_t ccRegs) const + bool canRename(uint32_t intRegs, uint32_t floatRegs, uint32_t vectorRegs, + uint32_t vecElemRegs, uint32_t ccRegs) const { return intRegs <= intMap.numFreeEntries() && floatRegs <= floatMap.numFreeEntries() && + vectorRegs <= vecMap.numFreeEntries() && + vecElemRegs <= vecElemMap.numFreeEntries() && ccRegs <= ccMap.numFreeEntries(); } + /** + * Set vector mode to Full or Elem. + * Ignore 'silent' modifications. + */ + void switchMode(VecMode newVecMode, UnifiedFreeList* freeList); }; diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 161d70b28..ac4ceed02 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2011-2012, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -194,6 +194,70 @@ class O3ThreadContext : public ThreadContext reg_idx)).index()); } + virtual const VecRegContainer& readVecReg(const RegId& id) const { + return readVecRegFlat(flattenRegId(id).index()); + } + + /** + * Read vector register operand for modification, hierarchical indexing. + */ + virtual VecRegContainer& getWritableVecReg(const RegId& id) { + return getWritableVecRegFlat(flattenRegId(id).index()); + } + + /** Vector Register Lane Interfaces. */ + /** @{ */ + /** Reads source vector 8bit operand. */ + virtual ConstVecLane8 + readVec8BitLaneReg(const RegId& id) const + { + return readVecLaneFlat<uint8_t>(flattenRegId(id).index(), + id.elemIndex()); + } + + /** Reads source vector 16bit operand. */ + virtual ConstVecLane16 + readVec16BitLaneReg(const RegId& id) const + { + return readVecLaneFlat<uint16_t>(flattenRegId(id).index(), + id.elemIndex()); + } + + /** Reads source vector 32bit operand. */ + virtual ConstVecLane32 + readVec32BitLaneReg(const RegId& id) const + { + return readVecLaneFlat<uint32_t>(flattenRegId(id).index(), + id.elemIndex()); + } + + /** Reads source vector 64bit operand. */ + virtual ConstVecLane64 + readVec64BitLaneReg(const RegId& id) const + { + return readVecLaneFlat<uint64_t>(flattenRegId(id).index(), + id.elemIndex()); + } + + /** Write a lane of the destination vector register. */ + virtual void setVecLane(const RegId& reg, + const LaneData<LaneSize::Byte>& val) + { return setVecLaneFlat(flattenRegId(reg).index(), reg.elemIndex(), val); } + virtual void setVecLane(const RegId& reg, + const LaneData<LaneSize::TwoByte>& val) + { return setVecLaneFlat(flattenRegId(reg).index(), reg.elemIndex(), val); } + virtual void setVecLane(const RegId& reg, + const LaneData<LaneSize::FourByte>& val) + { return setVecLaneFlat(flattenRegId(reg).index(), reg.elemIndex(), val); } + virtual void setVecLane(const RegId& reg, + const LaneData<LaneSize::EightByte>& val) + { return setVecLaneFlat(flattenRegId(reg).index(), reg.elemIndex(), val); } + /** @} */ + + virtual const VecElem& readVecElem(const RegId& reg) const { + return readVecElemFlat(flattenRegId(reg).index(), reg.elemIndex()); + } + virtual CCReg readCCReg(int reg_idx) { return readCCRegFlat(flattenRegId(RegId(CCRegClass, reg_idx)).index()); @@ -214,6 +278,14 @@ class O3ThreadContext : public ThreadContext reg_idx)).index(), val); } + virtual void setVecReg(const RegId& reg, const VecRegContainer& val) { + setVecRegFlat(flattenRegId(reg).index(), val); + } + + virtual void setVecElem(const RegId& reg, const VecElem& val) { + setVecElemFlat(flattenRegId(reg).index(), reg.elemIndex(), val); + } + virtual void setCCReg(int reg_idx, CCReg val) { setCCRegFlat(flattenRegId(RegId(CCRegClass, reg_idx)).index(), val); } @@ -298,6 +370,29 @@ class O3ThreadContext : public ThreadContext virtual FloatRegBits readFloatRegBitsFlat(int idx); virtual void setFloatRegBitsFlat(int idx, FloatRegBits val); + virtual const VecRegContainer& readVecRegFlat(int idx) const; + /** Read vector register operand for modification, flat indexing. */ + virtual VecRegContainer& getWritableVecRegFlat(int idx); + virtual void setVecRegFlat(int idx, const VecRegContainer& val); + + template <typename VecElem> + VecLaneT<VecElem, true> readVecLaneFlat(int idx, int lId) const + { + return cpu->template readArchVecLane<VecElem>(idx, lId, + thread->threadId()); + } + + template <typename LD> + void setVecLaneFlat(int idx, int lId, const LD& val) + { + cpu->template setArchVecLane(idx, lId, thread->threadId(), val); + } + + virtual const VecElem& readVecElemFlat(const RegIndex& idx, + const ElemIndex& elemIndex) const; + virtual void setVecElemFlat(const RegIndex& idx, const ElemIndex& elemIdx, + const VecElem& val); + virtual CCReg readCCRegFlat(int idx); virtual void setCCRegFlat(int idx, CCReg val); }; diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index c3f894275..2d109aea9 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 ARM Limited + * Copyright (c) 2010-2012, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -209,6 +209,28 @@ O3ThreadContext<Impl>::readFloatRegBitsFlat(int reg_idx) } template <class Impl> +const TheISA::VecRegContainer& +O3ThreadContext<Impl>::readVecRegFlat(int reg_id) const +{ + return cpu->readArchVecReg(reg_id, thread->threadId()); +} + +template <class Impl> +TheISA::VecRegContainer& +O3ThreadContext<Impl>::getWritableVecRegFlat(int reg_id) +{ + return cpu->getWritableArchVecReg(reg_id, thread->threadId()); +} + +template <class Impl> +const TheISA::VecElem& +O3ThreadContext<Impl>::readVecElemFlat(const RegIndex& idx, + const ElemIndex& elemIndex) const +{ + return cpu->readArchVecElem(idx, elemIndex, thread->threadId()); +} + +template <class Impl> TheISA::CCReg O3ThreadContext<Impl>::readCCRegFlat(int reg_idx) { @@ -244,6 +266,24 @@ O3ThreadContext<Impl>::setFloatRegBitsFlat(int reg_idx, FloatRegBits val) template <class Impl> void +O3ThreadContext<Impl>::setVecRegFlat(int reg_idx, const VecRegContainer& val) +{ + cpu->setArchVecReg(reg_idx, val, thread->threadId()); + + conditionalSquash(); +} + +template <class Impl> +void +O3ThreadContext<Impl>::setVecElemFlat(const RegIndex& idx, + const ElemIndex& elemIndex, const VecElem& val) +{ + cpu->setArchVecElem(idx, elemIndex, val, thread->threadId()); + conditionalSquash(); +} + +template <class Impl> +void O3ThreadContext<Impl>::setCCRegFlat(int reg_idx, TheISA::CCReg val) { cpu->setArchCCReg(reg_idx, val, thread->threadId()); |