rename_map.hh revision 12109
12440SN/A/* 22440SN/A * Copyright (c) 2015-2016 ARM Limited 32440SN/A * All rights reserved. 42440SN/A * 52440SN/A * The license below extends only to copyright in the software and shall 62440SN/A * not be construed as granting a license to any other intellectual 72440SN/A * property including but not limited to intellectual property relating 82440SN/A * to a hardware implementation of the functionality of the software 92440SN/A * licensed hereunder. You may use the software subject to the license 102440SN/A * terms below provided that you ensure that this notice is replicated 112440SN/A * unmodified and in its entirety in all distributions of the software, 122440SN/A * modified or unmodified, in source code or in binary form. 132440SN/A * 142440SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 152440SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 162440SN/A * All rights reserved. 172440SN/A * 182440SN/A * Redistribution and use in source and binary forms, with or without 192440SN/A * modification, are permitted provided that the following conditions are 202440SN/A * met: redistributions of source code must retain the above copyright 212440SN/A * notice, this list of conditions and the following disclaimer; 222440SN/A * redistributions in binary form must reproduce the above copyright 232440SN/A * notice, this list of conditions and the following disclaimer in the 242440SN/A * documentation and/or other materials provided with the distribution; 252440SN/A * neither the name of the copyright holders nor the names of its 262440SN/A * contributors may be used to endorse or promote products derived from 272665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302440SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312440SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322440SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332440SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342440SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352440SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362972Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 376327Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382440SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 395569Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 403120Sgblack@eecs.umich.edu * 412440SN/A * Authors: Kevin Lim 425569Snate@binkert.org * Steve Reinhardt 435569Snate@binkert.org */ 445569Snate@binkert.org 455569Snate@binkert.org#ifndef __CPU_O3_RENAME_MAP_HH__ 465569Snate@binkert.org#define __CPU_O3_RENAME_MAP_HH__ 475569Snate@binkert.org 482440SN/A#include <iostream> 495569Snate@binkert.org#include <utility> 505569Snate@binkert.org#include <vector> 514826Ssaidi@eecs.umich.edu 525569Snate@binkert.org#include "arch/types.hh" 535569Snate@binkert.org#include "config/the_isa.hh" 545569Snate@binkert.org#include "cpu/o3/free_list.hh" 555569Snate@binkert.org#include "cpu/o3/regfile.hh" 565570Snate@binkert.org#include "cpu/reg_class.hh" 575569Snate@binkert.org#include "enums/VecRegRenameMode.hh" 583577Sgblack@eecs.umich.edu 595569Snate@binkert.org/** 605569Snate@binkert.org * Register rename map for a single class of registers (e.g., integer 615569Snate@binkert.org * or floating point). Because the register class is implicitly 625569Snate@binkert.org * determined by the rename map instance being accessed, all 635570Snate@binkert.org * architectural register index parameters and values in this class 645569Snate@binkert.org * are relative (e.g., %fp2 is just index 2). 652440SN/A */ 665569Snate@binkert.orgclass SimpleRenameMap 675569Snate@binkert.org{ 685569Snate@binkert.org private: 695569Snate@binkert.org using Arch2PhysMap = std::vector<PhysRegIdPtr>; 705569Snate@binkert.org /** The acutal arch-to-phys register map */ 715569Snate@binkert.org Arch2PhysMap map; 722440SN/A public: 735569Snate@binkert.org using iterator = Arch2PhysMap::iterator; 745569Snate@binkert.org using const_iterator = Arch2PhysMap::const_iterator; 755569Snate@binkert.org private: 765569Snate@binkert.org 775569Snate@binkert.org /** 785569Snate@binkert.org * Pointer to the free list from which new physical registers 792440SN/A * should be allocated in rename() 805569Snate@binkert.org */ 815569Snate@binkert.org SimpleFreeList *freeList; 825569Snate@binkert.org 835569Snate@binkert.org /** 845569Snate@binkert.org * The architectural index of the zero register. This register is 852440SN/A * mapped but read-only, so we ignore attempts to rename it via 865569Snate@binkert.org * the rename() method. If there is no such register for this map 875569Snate@binkert.org * table, it should be set to an invalid index so that it never 885569Snate@binkert.org * matches. 895569Snate@binkert.org */ 905569Snate@binkert.org RegId zeroReg; 915569Snate@binkert.org 922440SN/A public: 935569Snate@binkert.org 945569Snate@binkert.org SimpleRenameMap(); 955569Snate@binkert.org 965569Snate@binkert.org ~SimpleRenameMap() {}; 975569Snate@binkert.org 982440SN/A /** 995569Snate@binkert.org * Because we have an array of rename maps (one per thread) in the CPU, 1005569Snate@binkert.org * it's awkward to initialize this object via the constructor. 1015569Snate@binkert.org * Instead, this method is used for initialization. 1025569Snate@binkert.org */ 1035569Snate@binkert.org void init(unsigned size, SimpleFreeList *_freeList, RegIndex _zeroReg); 1045569Snate@binkert.org 1055569Snate@binkert.org /** 1062440SN/A * Pair of a physical register and a physical register. Used to 1075569Snate@binkert.org * return the physical register that a logical register has been 1085569Snate@binkert.org * renamed to, and the previous physical register that the same 1095569Snate@binkert.org * logical register was previously mapped to. 1105569Snate@binkert.org */ 1115569Snate@binkert.org typedef std::pair<PhysRegIdPtr, PhysRegIdPtr> RenameInfo; 1125569Snate@binkert.org 1132440SN/A /** 1145569Snate@binkert.org * Tell rename map to get a new free physical register to remap 1155569Snate@binkert.org * the specified architectural register. 1165569Snate@binkert.org * @param arch_reg The architectural register to remap. 1175569Snate@binkert.org * @return A RenameInfo pair indicating both the new and previous 1185569Snate@binkert.org * physical registers. 1195569Snate@binkert.org */ 1202440SN/A RenameInfo rename(const RegId& arch_reg); 1215569Snate@binkert.org 1225569Snate@binkert.org /** 1235569Snate@binkert.org * Look up the physical register mapped to an architectural register. 1242440SN/A * @param arch_reg The architectural register to look up. 1255569Snate@binkert.org * @return The physical register it is currently mapped to. 1265569Snate@binkert.org */ 1275569Snate@binkert.org PhysRegIdPtr lookup(const RegId& arch_reg) const 1285569Snate@binkert.org { 1292440SN/A assert(arch_reg.flatIndex() <= map.size()); 1305569Snate@binkert.org return map[arch_reg.flatIndex()]; 1312440SN/A } 1325569Snate@binkert.org 1335569Snate@binkert.org /** 1342440SN/A * Update rename map with a specific mapping. Generally used to 1355569Snate@binkert.org * roll back to old mappings on a squash. 1365569Snate@binkert.org * @param arch_reg The architectural register to remap. 1375569Snate@binkert.org * @param phys_reg The physical register to remap it to. 1382440SN/A */ 1395569Snate@binkert.org void setEntry(const RegId& arch_reg, PhysRegIdPtr phys_reg) 1405569Snate@binkert.org { 1412440SN/A assert(arch_reg.flatIndex() <= map.size()); 1425569Snate@binkert.org map[arch_reg.flatIndex()] = phys_reg; 1435569Snate@binkert.org } 1445569Snate@binkert.org 1452440SN/A /** Return the number of free entries on the associated free list. */ 1465569Snate@binkert.org unsigned numFreeEntries() const { return freeList->numFreeRegs(); } 1475569Snate@binkert.org 1485569Snate@binkert.org /** Forward begin/cbegin to the map. */ 1492440SN/A /** @{ */ 1505569Snate@binkert.org iterator begin() { return map.begin(); } 1515569Snate@binkert.org const_iterator begin() const { return map.begin(); } 1525569Snate@binkert.org const_iterator cbegin() const { return map.cbegin(); } 1532440SN/A /** @} */ 1545569Snate@binkert.org 1555569Snate@binkert.org /** Forward end/cend to the map. */ 1565569Snate@binkert.org /** @{ */ 1575569Snate@binkert.org iterator end() { return map.end(); } 1585569Snate@binkert.org const_iterator end() const { return map.end(); } 1595569Snate@binkert.org const_iterator cend() const { return map.cend(); } 1602440SN/A /** @} */ 1612440SN/A}; 1626329Sgblack@eecs.umich.edu 1636329Sgblack@eecs.umich.edu 1646329Sgblack@eecs.umich.edu/** 1656329Sgblack@eecs.umich.edu * Unified register rename map for all classes of registers. Wraps a 1662440SN/A * set of class-specific rename maps. Methods that do not specify a 1672440SN/A * register class (e.g., rename()) take register ids, 1685569Snate@binkert.org * while methods that do specify a register class (e.g., renameInt()) 169 * take register indices. 170 */ 171class UnifiedRenameMap 172{ 173 private: 174 static constexpr uint32_t NVecElems = TheISA::NumVecElemPerVecReg; 175 using VecReg = TheISA::VecReg; 176 177 /** The integer register rename map */ 178 SimpleRenameMap intMap; 179 180 /** The floating-point register rename map */ 181 SimpleRenameMap floatMap; 182 183 /** The condition-code register rename map */ 184 SimpleRenameMap ccMap; 185 186 /** The vector register rename map */ 187 SimpleRenameMap vecMap; 188 189 /** The vector element register rename map */ 190 SimpleRenameMap vecElemMap; 191 192 using VecMode = Enums::VecRegRenameMode; 193 VecMode vecMode; 194 195 /** 196 * The register file object is used only to get PhysRegIdPtr 197 * on MiscRegs, as they are stored in it. 198 */ 199 PhysRegFile *regFile; 200 201 public: 202 203 typedef SimpleRenameMap::RenameInfo RenameInfo; 204 205 /** Default constructor. init() must be called prior to use. */ 206 UnifiedRenameMap() : regFile(nullptr) {}; 207 208 /** Destructor. */ 209 ~UnifiedRenameMap() {}; 210 211 /** Initializes rename map with given parameters. */ 212 void init(PhysRegFile *_regFile, 213 RegIndex _intZeroReg, 214 RegIndex _floatZeroReg, 215 UnifiedFreeList *freeList, 216 VecMode _mode); 217 218 /** 219 * Tell rename map to get a new free physical register to remap 220 * the specified architectural register. This version takes a 221 * RegId and reads the appropriate class-specific rename table. 222 * @param arch_reg The architectural register id to remap. 223 * @return A RenameInfo pair indicating both the new and previous 224 * physical registers. 225 */ 226 RenameInfo rename(const RegId& arch_reg) 227 { 228 switch (arch_reg.classValue()) { 229 case IntRegClass: 230 return intMap.rename(arch_reg); 231 case FloatRegClass: 232 return floatMap.rename(arch_reg); 233 case VecRegClass: 234 assert(vecMode == Enums::Full); 235 return vecMap.rename(arch_reg); 236 case VecElemClass: 237 assert(vecMode == Enums::Elem); 238 return vecElemMap.rename(arch_reg); 239 case CCRegClass: 240 return ccMap.rename(arch_reg); 241 case MiscRegClass: 242 { 243 // misc regs aren't really renamed, just remapped 244 PhysRegIdPtr phys_reg = lookup(arch_reg); 245 // Set the new register to the previous one to keep the same 246 // mapping throughout the execution. 247 return RenameInfo(phys_reg, phys_reg); 248 } 249 250 default: 251 panic("rename rename(): unknown reg class %s\n", 252 arch_reg.className()); 253 } 254 } 255 256 /** 257 * Look up the physical register mapped to an architectural register. 258 * This version takes a flattened architectural register id 259 * and calls the appropriate class-specific rename table. 260 * @param arch_reg The architectural register to look up. 261 * @return The physical register it is currently mapped to. 262 */ 263 PhysRegIdPtr lookup(const RegId& arch_reg) const 264 { 265 switch (arch_reg.classValue()) { 266 case IntRegClass: 267 return intMap.lookup(arch_reg); 268 269 case FloatRegClass: 270 return floatMap.lookup(arch_reg); 271 272 case VecRegClass: 273 assert(vecMode == Enums::Full); 274 return vecMap.lookup(arch_reg); 275 276 case VecElemClass: 277 assert(vecMode == Enums::Elem); 278 return vecElemMap.lookup(arch_reg); 279 280 case CCRegClass: 281 return ccMap.lookup(arch_reg); 282 283 case MiscRegClass: 284 // misc regs aren't really renamed, they keep the same 285 // mapping throughout the execution. 286 return regFile->getMiscRegId(arch_reg.flatIndex()); 287 288 default: 289 panic("rename lookup(): unknown reg class %s\n", 290 arch_reg.className()); 291 } 292 } 293 294 /** 295 * Update rename map with a specific mapping. Generally used to 296 * roll back to old mappings on a squash. This version takes a 297 * flattened architectural register id and calls the 298 * appropriate class-specific rename table. 299 * @param arch_reg The architectural register to remap. 300 * @param phys_reg The physical register to remap it to. 301 */ 302 void setEntry(const RegId& arch_reg, PhysRegIdPtr phys_reg) 303 { 304 switch (arch_reg.classValue()) { 305 case IntRegClass: 306 assert(phys_reg->isIntPhysReg()); 307 return intMap.setEntry(arch_reg, phys_reg); 308 309 case FloatRegClass: 310 assert(phys_reg->isFloatPhysReg()); 311 return floatMap.setEntry(arch_reg, phys_reg); 312 313 case VecRegClass: 314 assert(phys_reg->isVectorPhysReg()); 315 assert(vecMode == Enums::Full); 316 return vecMap.setEntry(arch_reg, phys_reg); 317 318 case VecElemClass: 319 assert(phys_reg->isVectorPhysElem()); 320 assert(vecMode == Enums::Elem); 321 return vecElemMap.setEntry(arch_reg, phys_reg); 322 323 case CCRegClass: 324 assert(phys_reg->isCCPhysReg()); 325 return ccMap.setEntry(arch_reg, phys_reg); 326 327 case MiscRegClass: 328 // Misc registers do not actually rename, so don't change 329 // their mappings. We end up here when a commit or squash 330 // tries to update or undo a hardwired misc reg nmapping, 331 // which should always be setting it to what it already is. 332 assert(phys_reg == lookup(arch_reg)); 333 return; 334 335 default: 336 panic("rename setEntry(): unknown reg class %s\n", 337 arch_reg.className()); 338 } 339 } 340 341 /** 342 * Return the minimum number of free entries across all of the 343 * register classes. The minimum is used so we guarantee that 344 * this number of entries is available regardless of which class 345 * of registers is requested. 346 */ 347 unsigned numFreeEntries() const 348 { 349 return std::min( 350 std::min(intMap.numFreeEntries(), floatMap.numFreeEntries()), 351 vecMode == Enums::Full ? vecMap.numFreeEntries() 352 : vecElemMap.numFreeEntries()); 353 } 354 355 unsigned numFreeIntEntries() const { return intMap.numFreeEntries(); } 356 unsigned numFreeFloatEntries() const { return floatMap.numFreeEntries(); } 357 unsigned numFreeVecEntries() const 358 { 359 return vecMode == Enums::Full 360 ? vecMap.numFreeEntries() 361 : vecElemMap.numFreeEntries(); 362 } 363 unsigned numFreeCCEntries() const { return ccMap.numFreeEntries(); } 364 365 /** 366 * Return whether there are enough registers to serve the request. 367 */ 368 bool canRename(uint32_t intRegs, uint32_t floatRegs, uint32_t vectorRegs, 369 uint32_t vecElemRegs, uint32_t ccRegs) const 370 { 371 return intRegs <= intMap.numFreeEntries() && 372 floatRegs <= floatMap.numFreeEntries() && 373 vectorRegs <= vecMap.numFreeEntries() && 374 vecElemRegs <= vecElemMap.numFreeEntries() && 375 ccRegs <= ccMap.numFreeEntries(); 376 } 377 /** 378 * Set vector mode to Full or Elem. 379 * Ignore 'silent' modifications. 380 */ 381 void switchMode(VecMode newVecMode, UnifiedFreeList* freeList); 382 383}; 384 385#endif //__CPU_O3_RENAME_MAP_HH__ 386