1/* 2 * Copyright (c) 2016-2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2004-2005 The Regents of The University of Michigan 15 * Copyright (c) 2013 Advanced Micro Devices, Inc. 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Kevin Lim 42 */ 43 44#ifndef __CPU_O3_FREE_LIST_HH__ 45#define __CPU_O3_FREE_LIST_HH__ 46 47#include <iostream> 48#include <queue> 49#include <vector> 50 51#include "base/logging.hh" 52#include "base/trace.hh" 53#include "cpu/o3/comm.hh" 54#include "cpu/o3/regfile.hh" 55#include "debug/FreeList.hh" 56 57/** 58 * Free list for a single class of registers (e.g., integer 59 * or floating point). Because the register class is implicitly 60 * determined by the rename map instance being accessed, all 61 * architectural register index parameters and values in this class 62 * are relative (e.g., %fp2 is just index 2). 63 */ 64class SimpleFreeList 65{ 66 private: 67 68 /** The actual free list */ 69 std::queue<PhysRegIdPtr> freeRegs; 70 71 public: 72 73 SimpleFreeList() {}; 74 75 /** Add a physical register to the free list */ 76 void addReg(PhysRegIdPtr reg) { freeRegs.push(reg); } 77 78 /** Add physical registers to the free list */ 79 template<class InputIt> 80 void 81 addRegs(InputIt first, InputIt last) { 82 std::for_each(first, last, [this](typename InputIt::value_type& reg) { 83 this->freeRegs.push(®); 84 }); 85 } 86 87 /** Get the next available register from the free list */ 88 PhysRegIdPtr getReg() 89 { 90 assert(!freeRegs.empty()); 91 PhysRegIdPtr free_reg = freeRegs.front(); 92 freeRegs.pop(); 93 return free_reg; 94 } 95 96 /** Return the number of free registers on the list. */ 97 unsigned numFreeRegs() const { return freeRegs.size(); } 98 99 /** True iff there are free registers on the list. */ 100 bool hasFreeRegs() const { return !freeRegs.empty(); } 101}; 102 103 104/** 105 * FreeList class that simply holds the list of free integer and floating 106 * point registers. Can request for a free register of either type, and 107 * also send back free registers of either type. This is a very simple 108 * class, but it should be sufficient for most implementations. Like all 109 * other classes, it assumes that the indices for the floating point 110 * registers starts after the integer registers end. Hence the variable 111 * numPhysicalIntRegs is logically equivalent to the baseFP dependency. 112 * Note that while this most likely should be called FreeList, the name 113 * "FreeList" is used in a typedef within the CPU Policy, and therefore no 114 * class can be named simply "FreeList". 115 * @todo: Give a better name to the base FP dependency. 116 */ 117class UnifiedFreeList 118{ 119 private: 120 121 /** The object name, for DPRINTF. We have to declare this 122 * explicitly because Scoreboard is not a SimObject. */ 123 const std::string _name; 124 125 /** The list of free integer registers. */ 126 SimpleFreeList intList; 127 128 /** The list of free floating point registers. */ 129 SimpleFreeList floatList; 130 131 /** The following two are exclusive interfaces. */ 132 /** @{ */ 133 /** The list of free vector registers. */ 134 SimpleFreeList vecList; 135 136 /** The list of free vector element registers. */ 137 SimpleFreeList vecElemList; 138 /** @} */ 139 140 /** The list of free predicate registers. */ 141 SimpleFreeList predList; 142 143 /** The list of free condition-code registers. */ 144 SimpleFreeList ccList; 145 146 /** 147 * The register file object is used only to distinguish integer 148 * from floating-point physical register indices. 149 */ 150 PhysRegFile *regFile; 151 152 /* 153 * We give UnifiedRenameMap internal access so it can get at the 154 * internal per-class free lists and associate those with its 155 * per-class rename maps. See UnifiedRenameMap::init(). 156 */ 157 friend class UnifiedRenameMap; 158 159 public: 160 /** Constructs a free list. 161 * @param _numPhysicalIntRegs Number of physical integer registers. 162 * @param reservedIntRegs Number of integer registers already 163 * used by initial mappings. 164 * @param _numPhysicalFloatRegs Number of physical fp registers. 165 * @param reservedFloatRegs Number of fp registers already 166 * used by initial mappings. 167 */ 168 UnifiedFreeList(const std::string &_my_name, PhysRegFile *_regFile); 169 170 /** Gives the name of the freelist. */ 171 std::string name() const { return _name; }; 172 173 /** Returns a pointer to the condition-code free list */ 174 SimpleFreeList *getCCList() { return &ccList; } 175 176 /** Gets a free integer register. */ 177 PhysRegIdPtr getIntReg() { return intList.getReg(); } 178 179 /** Gets a free fp register. */ 180 PhysRegIdPtr getFloatReg() { return floatList.getReg(); } 181 182 /** Gets a free vector register. */ 183 PhysRegIdPtr getVecReg() { return vecList.getReg(); } 184 185 /** Gets a free vector elemenet register. */ 186 PhysRegIdPtr getVecElem() { return vecElemList.getReg(); } 187 188 /** Gets a free predicate register. */ 189 PhysRegIdPtr getVecPredReg() { return predList.getReg(); } 190 191 /** Gets a free cc register. */ 192 PhysRegIdPtr getCCReg() { return ccList.getReg(); } 193 194 /** Adds a register back to the free list. */ 195 void addReg(PhysRegIdPtr freed_reg); 196 197 /** Adds a register back to the free list. */ 198 template<class InputIt> 199 void addRegs(InputIt first, InputIt last); 200 201 /** Adds an integer register back to the free list. */ 202 void addIntReg(PhysRegIdPtr freed_reg) { intList.addReg(freed_reg); } 203 204 /** Adds a fp register back to the free list. */ 205 void addFloatReg(PhysRegIdPtr freed_reg) { floatList.addReg(freed_reg); } 206 207 /** Adds a vector register back to the free list. */ 208 void addVecReg(PhysRegIdPtr freed_reg) { vecList.addReg(freed_reg); } 209 210 /** Adds a vector element register back to the free list. */ 211 void addVecElem(PhysRegIdPtr freed_reg) { 212 vecElemList.addReg(freed_reg); 213 } 214 215 /** Adds a predicate register back to the free list. */ 216 void addVecPredReg(PhysRegIdPtr freed_reg) { predList.addReg(freed_reg); } 217 218 /** Adds a cc register back to the free list. */ 219 void addCCReg(PhysRegIdPtr freed_reg) { ccList.addReg(freed_reg); } 220 221 /** Checks if there are any free integer registers. */ 222 bool hasFreeIntRegs() const { return intList.hasFreeRegs(); } 223 224 /** Checks if there are any free fp registers. */ 225 bool hasFreeFloatRegs() const { return floatList.hasFreeRegs(); } 226 227 /** Checks if there are any free vector registers. */ 228 bool hasFreeVecRegs() const { return vecList.hasFreeRegs(); } 229 230 /** Checks if there are any free vector registers. */ 231 bool hasFreeVecElems() const { return vecElemList.hasFreeRegs(); } 232 233 /** Checks if there are any free predicate registers. */ 234 bool hasFreeVecPredRegs() const { return predList.hasFreeRegs(); } 235 236 /** Checks if there are any free cc registers. */ 237 bool hasFreeCCRegs() const { return ccList.hasFreeRegs(); } 238 239 /** Returns the number of free integer registers. */ 240 unsigned numFreeIntRegs() const { return intList.numFreeRegs(); } 241 242 /** Returns the number of free fp registers. */ 243 unsigned numFreeFloatRegs() const { return floatList.numFreeRegs(); } 244 245 /** Returns the number of free vector registers. */ 246 unsigned numFreeVecRegs() const { return vecList.numFreeRegs(); } 247 248 /** Returns the number of free vector registers. */ 249 unsigned numFreeVecElems() const { return vecElemList.numFreeRegs(); } 250 251 /** Returns the number of free predicate registers. */ 252 unsigned numFreeVecPredRegs() const { return predList.numFreeRegs(); } 253 254 /** Returns the number of free cc registers. */ 255 unsigned numFreeCCRegs() const { return ccList.numFreeRegs(); } 256}; 257 258template<class InputIt> 259inline void 260UnifiedFreeList::addRegs(InputIt first, InputIt last) 261{ 262 // Are there any registers to add? 263 if (first == last) 264 return; 265 266 panic_if((first != last) && 267 first->classValue() != (last-1)->classValue(), 268 "Attempt to add mixed type regs: %s and %s", 269 first->className(), 270 (last-1)->className()); 271 switch (first->classValue()) { 272 case IntRegClass: 273 intList.addRegs(first, last); 274 break; 275 case FloatRegClass: 276 floatList.addRegs(first, last); 277 break; 278 case VecRegClass: 279 vecList.addRegs(first, last); 280 break; 281 case VecElemClass: 282 vecElemList.addRegs(first, last); 283 break; 284 case VecPredRegClass: 285 predList.addRegs(first, last); 286 break; 287 case CCRegClass: 288 ccList.addRegs(first, last); 289 break; 290 default: 291 panic("Unexpected RegClass (%s)", 292 first->className()); 293 } 294 295} 296 297inline void 298UnifiedFreeList::addReg(PhysRegIdPtr freed_reg) 299{ 300 DPRINTF(FreeList,"Freeing register %i (%s).\n", freed_reg->index(), 301 freed_reg->className()); 302 //Might want to add in a check for whether or not this register is 303 //already in there. A bit vector or something similar would be useful. 304 switch (freed_reg->classValue()) { 305 case IntRegClass: 306 intList.addReg(freed_reg); 307 break; 308 case FloatRegClass: 309 floatList.addReg(freed_reg); 310 break; 311 case VecRegClass: 312 vecList.addReg(freed_reg); 313 break; 314 case VecElemClass: 315 vecElemList.addReg(freed_reg); 316 break; 317 case VecPredRegClass: 318 predList.addReg(freed_reg); 319 break; 320 case CCRegClass: 321 ccList.addReg(freed_reg); 322 break; 323 default: 324 panic("Unexpected RegClass (%s)", 325 freed_reg->className()); 326 } 327 328 // These assert conditions ensure that the number of free 329 // registers are not more than the # of total Physical Registers. 330 // If this were false, it would mean that registers 331 // have been freed twice, overflowing the free register 332 // pool and potentially crashing SMT workloads. 333 // ---- 334 // Comment out for now so as to not potentially break 335 // CMP and single-threaded workloads 336 // ---- 337 // assert(freeIntRegs.size() <= numPhysicalIntRegs); 338 // assert(freeFloatRegs.size() <= numPhysicalFloatRegs); 339} 340 341 342#endif // __CPU_O3_FREE_LIST_HH__ 343