/* * 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" /** * Simple physical register file class. */ class PhysRegFile { private: typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; typedef union { FloatReg d; FloatRegBits q; } PhysFloatReg; /** Integer register file. */ IntReg *intRegFile; /** Floating point register file. */ PhysFloatReg *floatRegFile; /** * 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. */ unsigned baseFloatRegIndex; /** 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); /** * Destructor to free resources */ ~PhysRegFile(); /** @return the number of integer physical registers. */ unsigned numIntPhysRegs() const { return baseFloatRegIndex; } /** @return the number of floating-point physical registers. */ unsigned numFloatPhysRegs() const { return totalNumRegs - baseFloatRegIndex; } /** @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 < 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; } /** 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; } }; inline PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, unsigned _numPhysicalFloatRegs) : baseFloatRegIndex(_numPhysicalIntRegs), totalNumRegs(_numPhysicalIntRegs + _numPhysicalFloatRegs) { intRegFile = new IntReg[_numPhysicalIntRegs]; floatRegFile = new PhysFloatReg[_numPhysicalFloatRegs]; memset(intRegFile, 0, sizeof(IntReg) * _numPhysicalIntRegs); memset(floatRegFile, 0, sizeof(PhysFloatReg) * _numPhysicalFloatRegs); } inline PhysRegFile::~PhysRegFile() { delete intRegFile; delete floatRegFile; } #endif //__CPU_O3_REGFILE_HH__