/* * 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" 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; typedef union { FloatReg d; FloatRegBits q; } PhysFloatReg; /** Integer register file. */ std::vector intRegFile; /** 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 * initial indices mapping to the integer registers, followed * immediately by the floating-point registers. Thus the first * floating-point index is equal to the number of integer * registers. * * Note that this internal organizational detail on how physical * register file indices are ordered should *NOT* be exposed * outside of this class. Other classes can use the is*PhysReg() * methods to map from a physical register index to a class * without knowing the internal structure of the index map. */ 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; public: /** * Constructs a physical register file with the specified amount of * integer and floating point registers. */ PhysRegFile(unsigned _numPhysicalIntRegs, unsigned _numPhysicalFloatRegs, unsigned _numPhysicalCCRegs); /** * Destructor to free resources */ ~PhysRegFile() {} /** Initialize the free list */ void initFreeList(UnifiedFreeList *freeList); /** @return the number of integer physical registers. */ unsigned numIntPhysRegs() const { return baseFloatRegIndex; } /** @return the number of floating-point physical registers. */ unsigned numFloatPhysRegs() const { 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; } /** * @return true if the specified physical register index * corresponds to an integer physical register. */ bool isIntPhysReg(PhysRegIndex reg_idx) const { return 0 <= reg_idx && reg_idx < baseFloatRegIndex; } /** * @return true if the specified physical register index * corresponds to a floating-point physical register. */ bool isFloatPhysReg(PhysRegIndex reg_idx) const { 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. */ uint64_t readIntReg(PhysRegIndex reg_idx) const { assert(isIntPhysReg(reg_idx)); DPRINTF(IEW, "RegFile: Access to int register %i, has data " "%#x\n", int(reg_idx), intRegFile[reg_idx]); return intRegFile[reg_idx]; } /** Reads a floating point register (double precision). */ FloatReg readFloatReg(PhysRegIndex reg_idx) const { assert(isFloatPhysReg(reg_idx)); // Remove the base Float reg dependency. PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; DPRINTF(IEW, "RegFile: Access to float register %i, has " "data %#x\n", int(reg_idx), floatRegFile[reg_offset].q); return floatRegFile[reg_offset].d; } FloatRegBits readFloatRegBits(PhysRegIndex reg_idx) const { assert(isFloatPhysReg(reg_idx)); // Remove the base Float reg dependency. PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; FloatRegBits floatRegBits = floatRegFile[reg_offset].q; DPRINTF(IEW, "RegFile: Access to float register %i as int, " "has data %#x\n", int(reg_idx), (uint64_t)floatRegBits); 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) { assert(isIntPhysReg(reg_idx)); DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n", int(reg_idx), val); if (reg_idx != TheISA::ZeroReg) intRegFile[reg_idx] = val; } /** Sets a double precision floating point register to the given value. */ void setFloatReg(PhysRegIndex reg_idx, FloatReg val) { assert(isFloatPhysReg(reg_idx)); // Remove the base Float reg dependency. PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", int(reg_idx), (uint64_t)val); #if THE_ISA == ALPHA_ISA if (reg_offset != TheISA::ZeroReg) #endif floatRegFile[reg_offset].d = val; } void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val) { assert(isFloatPhysReg(reg_idx)); // Remove the base Float reg dependency. PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", int(reg_idx), (uint64_t)val); 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; } }; #endif //__CPU_O3_REGFILE_HH__