/* * 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 */ #ifndef __CPU_O3_FREE_LIST_HH__ #define __CPU_O3_FREE_LIST_HH__ #include #include #include #include "base/logging.hh" #include "base/trace.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/regfile.hh" #include "debug/FreeList.hh" /** * Free list for a single class of registers (e.g., integer * or floating point). Because the register class is implicitly * determined by the rename map instance being accessed, all * architectural register index parameters and values in this class * are relative (e.g., %fp2 is just index 2). */ class SimpleFreeList { private: /** The actual free list */ std::queue freeRegs; public: SimpleFreeList() {}; /** Add a physical register to the free list */ void addReg(PhysRegIdPtr reg) { freeRegs.push(reg); } /** Add physical registers to the free list */ template 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() { assert(!freeRegs.empty()); PhysRegIdPtr free_reg = freeRegs.front(); freeRegs.pop(); return free_reg; } /** Return the number of free registers on the list. */ unsigned numFreeRegs() const { return freeRegs.size(); } /** True iff there are free registers on the list. */ bool hasFreeRegs() const { return !freeRegs.empty(); } }; /** * FreeList class that simply holds the list of free integer and floating * point registers. Can request for a free register of either type, and * also send back free registers of either type. This is a very simple * class, but it should be sufficient for most implementations. Like all * other classes, it assumes that the indices for the floating point * registers starts after the integer registers end. Hence the variable * numPhysicalIntRegs is logically equivalent to the baseFP dependency. * Note that while this most likely should be called FreeList, the name * "FreeList" is used in a typedef within the CPU Policy, and therefore no * class can be named simply "FreeList". * @todo: Give a better name to the base FP dependency. */ class UnifiedFreeList { private: /** The object name, for DPRINTF. We have to declare this * explicitly because Scoreboard is not a SimObject. */ const std::string _name; /** The list of free integer registers. */ SimpleFreeList intList; /** 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; /** * The register file object is used only to distinguish integer * from floating-point physical register indices. */ PhysRegFile *regFile; /* * We give UnifiedRenameMap internal access so it can get at the * internal per-class free lists and associate those with its * per-class rename maps. See UnifiedRenameMap::init(). */ friend class UnifiedRenameMap; public: /** Constructs a free list. * @param _numPhysicalIntRegs Number of physical integer registers. * @param reservedIntRegs Number of integer registers already * used by initial mappings. * @param _numPhysicalFloatRegs Number of physical fp registers. * @param reservedFloatRegs Number of fp registers already * used by initial mappings. */ UnifiedFreeList(const std::string &_my_name, PhysRegFile *_regFile); /** 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. */ PhysRegIdPtr getIntReg() { return intList.getReg(); } /** 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 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); } /** 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 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(); } /** 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 vector registers. */ unsigned numFreeVecRegs() const { return vecList.numFreeRegs(); } /** Returns the number of free cc registers. */ unsigned numFreeCCRegs() const { return ccList.numFreeRegs(); } }; template 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) { DPRINTF(FreeList,"Freeing register %i (%s).\n", freed_reg->index(), freed_reg->className()); //Might want to add in a check for whether or not this register is //already in there. A bit vector or something similar would be useful. switch (freed_reg->classValue()) { case IntRegClass: intList.addReg(freed_reg); break; 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; default: panic("Unexpected RegClass (%s)", freed_reg->className()); } // These assert conditions ensure that the number of free // registers are not more than the # of total Physical Registers. // If this were false, it would mean that registers // have been freed twice, overflowing the free register // pool and potentially crashing SMT workloads. // ---- // Comment out for now so as to not potentially break // CMP and single-threaded workloads // ---- // assert(freeIntRegs.size() <= numPhysicalIntRegs); // assert(freeFloatRegs.size() <= numPhysicalFloatRegs); } #endif // __CPU_O3_FREE_LIST_HH__