/* * 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim * Gabe Black */ #ifndef __CPU_O3_REGFILE_HH__ #define __CPU_O3_REGFILE_HH__ #include #include "arch/isa_traits.hh" #include "arch/kernel_stats.hh" #include "arch/types.hh" #include "base/trace.hh" #include "config/the_isa.hh" #include "cpu/o3/comm.hh" #include "debug/IEW.hh" #include "enums/VecRegRenameMode.hh" #include "debug/IFT.hh" class UnifiedFreeList; /** * Simple physical register file class. */ class PhysRegFile { private: typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::CCReg CCReg; using VecElem = TheISA::VecElem; using VecRegContainer = TheISA::VecRegContainer; using PhysIds = std::vector; using VecMode = Enums::VecRegRenameMode; public: using IdRange = std::pair; private: static constexpr auto NumVecElemPerVecReg = TheISA::NumVecElemPerVecReg; typedef union { FloatReg d; FloatRegBits q; } PhysFloatReg; /** Integer register file. */ std::vector intRegFile; std::vector intRegIds; std::vector intTaintMap; /** Floating point register file. */ std::vector floatRegFile; std::vector floatRegIds; std::vector floatTaintMap; /** Vector register file. */ std::vector vectorRegFile; std::vector vecRegIds; std::vector vecElemIds; std::vector vecTaintMap; /** Condition-code register file. */ std::vector ccRegFile; std::vector ccRegIds; std::vector ccTaintMap; /** Misc Reg Ids */ std::vector miscRegIds; std::vector miscTaintMap; /** * Number of physical general purpose registers */ unsigned numPhysicalIntRegs; /** * Number of physical floating point registers */ unsigned numPhysicalFloatRegs; /** * 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 * integer and floating point registers. */ PhysRegFile(unsigned _numPhysicalIntRegs, unsigned _numPhysicalFloatRegs, unsigned _numPhysicalVecRegs, unsigned _numPhysicalCCRegs, VecMode vmode ); /** * Destructor to free resources */ ~PhysRegFile() {} /** Initialize the free list */ void initFreeList(UnifiedFreeList *freeList); /** @return the number of integer physical registers. */ unsigned numIntPhysRegs() const { return numPhysicalIntRegs; } /** @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; } /** @return the total number of physical registers. */ unsigned totalNumPhysRegs() const { return totalNumRegs; } /** Gets a misc register PhysRegIdPtr. */ PhysRegIdPtr getMiscRegId(RegIndex reg_idx) { return &miscRegIds[reg_idx]; } /** Set a physical register as tainted */ void setTaint(PhysRegIdPtr phys_reg, bool taintvalue) { RegIndex idx = phys_reg->index(); switch (phys_reg->classValue()) { case IntRegClass: intTaintMap[idx] = taintvalue; break; case FloatRegClass: floatTaintMap[idx] = taintvalue; break; case CCRegClass: ccTaintMap[idx] = taintvalue; break; case MiscRegClass: miscTaintMap[idx] = taintvalue; break; default: warn_once("taint for vector registers not supported yet\n"); break; } DPRINTF(IFT, "register %s %d is set to %d\n", phys_reg->className(), idx, taintvalue); } bool regTainted(PhysRegIdPtr phys_reg) { RegIndex idx = phys_reg->index(); bool result; switch (phys_reg->classValue()) { case IntRegClass: result = intTaintMap[idx]; break; case FloatRegClass: result = floatTaintMap[idx]; break; case CCRegClass: result = ccTaintMap[idx]; break; case MiscRegClass: result = miscTaintMap[idx]; break; default: warn_once("taint for vector registers not supported yet\n"); return false; } DPRINTF(IFT, "register %s %d is %s\n", phys_reg->className(), idx, result?"tained":"not tainted"); return result; } /** Reads an integer register. */ uint64_t readIntReg(PhysRegIdPtr phys_reg) const { assert(phys_reg->isIntPhysReg()); DPRINTF(IEW, "RegFile: Access to int register %i, has data " "%#x\n", phys_reg->index(), intRegFile[phys_reg->index()]); return intRegFile[phys_reg->index()]; } /** Reads a floating point register (double precision). */ FloatReg readFloatReg(PhysRegIdPtr phys_reg) const { assert(phys_reg->isFloatPhysReg()); DPRINTF(IEW, "RegFile: Access to float register %i, has " "data %#x\n", phys_reg->index(), floatRegFile[phys_reg->index()].q); return floatRegFile[phys_reg->index()].d; } FloatRegBits readFloatRegBits(PhysRegIdPtr phys_reg) const { assert(phys_reg->isFloatPhysReg()); FloatRegBits floatRegBits = floatRegFile[phys_reg->index()].q; DPRINTF(IEW, "RegFile: Access to float register %i as int, " "has data %#x\n", phys_reg->index(), (uint64_t)floatRegBits); 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().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(readVecReg(phys_reg)); } /** Reads a vector register lane. */ template VecLaneT readVecLane(PhysRegIdPtr phys_reg) const { return readVecReg(phys_reg).laneView(); } /** Reads a vector register lane. */ template VecLaneT readVecLane(PhysRegIdPtr phys_reg) const { return readVecReg(phys_reg).laneView(phys_reg->elemIndex()); } /** Get a vector register lane for modification. */ template 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( 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(); 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) { assert(phys_reg->isCCPhysReg()); DPRINTF(IEW, "RegFile: Access to cc register %i, has " "data %#x\n", phys_reg->index(), ccRegFile[phys_reg->index()]); return ccRegFile[phys_reg->index()]; } /** Sets an integer register to the given value. */ void setIntReg(PhysRegIdPtr phys_reg, uint64_t val) { assert(phys_reg->isIntPhysReg()); DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n", phys_reg->index(), val); if (!phys_reg->isZeroReg()) intRegFile[phys_reg->index()] = val; } /** Sets a double precision floating point register to the given value. */ void setFloatReg(PhysRegIdPtr phys_reg, FloatReg val) { assert(phys_reg->isFloatPhysReg()); DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", phys_reg->index(), (uint64_t)val); if (!phys_reg->isZeroReg()) floatRegFile[phys_reg->index()].d = val; } void setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val) { assert(phys_reg->isFloatPhysReg()); DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", phys_reg->index(), (uint64_t)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()[phys_reg->elemIndex()] = val; } /** Sets a condition-code register to the given value. */ void setCCReg(PhysRegIdPtr phys_reg, CCReg val) { assert(phys_reg->isCCPhysReg()); DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n", phys_reg->index(), (uint64_t)val); 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); }; #endif //__CPU_O3_REGFILE_HH__