rename_map.hh revision 10537
11689SN/A/* 21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 39919Ssteve.reinhardt@amd.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 41689SN/A * All rights reserved. 51689SN/A * 61689SN/A * Redistribution and use in source and binary forms, with or without 71689SN/A * modification, are permitted provided that the following conditions are 81689SN/A * met: redistributions of source code must retain the above copyright 91689SN/A * notice, this list of conditions and the following disclaimer; 101689SN/A * redistributions in binary form must reproduce the above copyright 111689SN/A * notice, this list of conditions and the following disclaimer in the 121689SN/A * documentation and/or other materials provided with the distribution; 131689SN/A * neither the name of the copyright holders nor the names of its 141689SN/A * contributors may be used to endorse or promote products derived from 151689SN/A * this software without specific prior written permission. 161689SN/A * 171689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 181689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 191689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 201689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 211689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 221689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 231689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 241689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 251689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 261689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 271689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 309919Ssteve.reinhardt@amd.com * Steve Reinhardt 311689SN/A */ 321689SN/A 331060SN/A// Todo: Create destructor. 341061SN/A// Have it so that there's a more meaningful name given to the variable 351060SN/A// that marks the beginning of the FP registers. 361060SN/A 372292SN/A#ifndef __CPU_O3_RENAME_MAP_HH__ 382292SN/A#define __CPU_O3_RENAME_MAP_HH__ 391060SN/A 401060SN/A#include <iostream> 411461SN/A#include <utility> 421060SN/A#include <vector> 431060SN/A 446658Snate@binkert.org#include "arch/types.hh" 456658Snate@binkert.org#include "config/the_isa.hh" 461717SN/A#include "cpu/o3/free_list.hh" 479919Ssteve.reinhardt@amd.com#include "cpu/o3/regfile.hh" 489919Ssteve.reinhardt@amd.com#include "cpu/reg_class.hh" 491060SN/A 509919Ssteve.reinhardt@amd.com/** 519919Ssteve.reinhardt@amd.com * Register rename map for a single class of registers (e.g., integer 529919Ssteve.reinhardt@amd.com * or floating point). Because the register class is implicitly 539919Ssteve.reinhardt@amd.com * determined by the rename map instance being accessed, all 549919Ssteve.reinhardt@amd.com * architectural register index parameters and values in this class 559919Ssteve.reinhardt@amd.com * are relative (e.g., %fp2 is just index 2). 569919Ssteve.reinhardt@amd.com */ 571060SN/Aclass SimpleRenameMap 581060SN/A{ 599919Ssteve.reinhardt@amd.com public: 609919Ssteve.reinhardt@amd.com 612107SN/A typedef TheISA::RegIndex RegIndex; 629919Ssteve.reinhardt@amd.com 639919Ssteve.reinhardt@amd.com private: 649919Ssteve.reinhardt@amd.com 659919Ssteve.reinhardt@amd.com /** The acutal arch-to-phys register map */ 669919Ssteve.reinhardt@amd.com std::vector<PhysRegIndex> map; 679919Ssteve.reinhardt@amd.com 689919Ssteve.reinhardt@amd.com /** 699919Ssteve.reinhardt@amd.com * Pointer to the free list from which new physical registers 709919Ssteve.reinhardt@amd.com * should be allocated in rename() 719919Ssteve.reinhardt@amd.com */ 729919Ssteve.reinhardt@amd.com SimpleFreeList *freeList; 739919Ssteve.reinhardt@amd.com 749919Ssteve.reinhardt@amd.com /** 759919Ssteve.reinhardt@amd.com * The architectural index of the zero register. This register is 769919Ssteve.reinhardt@amd.com * mapped but read-only, so we ignore attempts to rename it via 779919Ssteve.reinhardt@amd.com * the rename() method. If there is no such register for this map 789919Ssteve.reinhardt@amd.com * table, it should be set to an invalid index so that it never 799919Ssteve.reinhardt@amd.com * matches. 809919Ssteve.reinhardt@amd.com */ 819919Ssteve.reinhardt@amd.com RegIndex zeroReg; 829919Ssteve.reinhardt@amd.com 831060SN/A public: 849919Ssteve.reinhardt@amd.com 859919Ssteve.reinhardt@amd.com SimpleRenameMap(); 869919Ssteve.reinhardt@amd.com 879919Ssteve.reinhardt@amd.com ~SimpleRenameMap() {}; 889919Ssteve.reinhardt@amd.com 891060SN/A /** 909919Ssteve.reinhardt@amd.com * Because we have an array of rename maps (one per thread) in the CPU, 919919Ssteve.reinhardt@amd.com * it's awkward to initialize this object via the constructor. 929919Ssteve.reinhardt@amd.com * Instead, this method is used for initialization. 931060SN/A */ 949919Ssteve.reinhardt@amd.com void init(unsigned size, SimpleFreeList *_freeList, RegIndex _zeroReg); 951060SN/A 961060SN/A /** 971060SN/A * Pair of a physical register and a physical register. Used to 981060SN/A * return the physical register that a logical register has been 991060SN/A * renamed to, and the previous physical register that the same 1001060SN/A * logical register was previously mapped to. 1011060SN/A */ 1021461SN/A typedef std::pair<PhysRegIndex, PhysRegIndex> RenameInfo; 1031060SN/A 1049919Ssteve.reinhardt@amd.com /** 1059919Ssteve.reinhardt@amd.com * Tell rename map to get a new free physical register to remap 1069919Ssteve.reinhardt@amd.com * the specified architectural register. 1079919Ssteve.reinhardt@amd.com * @param arch_reg The architectural register to remap. 1089919Ssteve.reinhardt@amd.com * @return A RenameInfo pair indicating both the new and previous 1099919Ssteve.reinhardt@amd.com * physical registers. 1109919Ssteve.reinhardt@amd.com */ 1119919Ssteve.reinhardt@amd.com RenameInfo rename(RegIndex arch_reg); 1129919Ssteve.reinhardt@amd.com 1139919Ssteve.reinhardt@amd.com /** 1149919Ssteve.reinhardt@amd.com * Look up the physical register mapped to an architectural register. 1159919Ssteve.reinhardt@amd.com * @param arch_reg The architectural register to look up. 1169919Ssteve.reinhardt@amd.com * @return The physical register it is currently mapped to. 1179919Ssteve.reinhardt@amd.com */ 1189919Ssteve.reinhardt@amd.com PhysRegIndex lookup(RegIndex arch_reg) const 1199919Ssteve.reinhardt@amd.com { 1209919Ssteve.reinhardt@amd.com assert(arch_reg < map.size()); 1219919Ssteve.reinhardt@amd.com return map[arch_reg]; 1229919Ssteve.reinhardt@amd.com } 1239919Ssteve.reinhardt@amd.com 1249919Ssteve.reinhardt@amd.com /** 1259919Ssteve.reinhardt@amd.com * Update rename map with a specific mapping. Generally used to 1269919Ssteve.reinhardt@amd.com * roll back to old mappings on a squash. 1279919Ssteve.reinhardt@amd.com * @param arch_reg The architectural register to remap. 1289919Ssteve.reinhardt@amd.com * @param phys_reg The physical register to remap it to. 1299919Ssteve.reinhardt@amd.com */ 1309919Ssteve.reinhardt@amd.com void setEntry(RegIndex arch_reg, PhysRegIndex phys_reg) 1319919Ssteve.reinhardt@amd.com { 1329919Ssteve.reinhardt@amd.com map[arch_reg] = phys_reg; 1339919Ssteve.reinhardt@amd.com } 1349919Ssteve.reinhardt@amd.com 1359919Ssteve.reinhardt@amd.com /** Return the number of free entries on the associated free list. */ 1369919Ssteve.reinhardt@amd.com unsigned numFreeEntries() const { return freeList->numFreeRegs(); } 1379919Ssteve.reinhardt@amd.com}; 1389919Ssteve.reinhardt@amd.com 1399919Ssteve.reinhardt@amd.com 1409919Ssteve.reinhardt@amd.com/** 1419919Ssteve.reinhardt@amd.com * Unified register rename map for all classes of registers. Wraps a 1429919Ssteve.reinhardt@amd.com * set of class-specific rename maps. Methods that do not specify a 1439919Ssteve.reinhardt@amd.com * register class (e.g., rename()) take unified register indices, 1449919Ssteve.reinhardt@amd.com * while methods that do specify a register class (e.g., renameInt()) 1459919Ssteve.reinhardt@amd.com * take relative register indices. See http://gem5.org/Register_Indexing. 1469919Ssteve.reinhardt@amd.com */ 1479919Ssteve.reinhardt@amd.comclass UnifiedRenameMap 1489919Ssteve.reinhardt@amd.com{ 1499919Ssteve.reinhardt@amd.com private: 1509919Ssteve.reinhardt@amd.com 1519919Ssteve.reinhardt@amd.com /** The integer register rename map */ 1529919Ssteve.reinhardt@amd.com SimpleRenameMap intMap; 1539919Ssteve.reinhardt@amd.com 1549919Ssteve.reinhardt@amd.com /** The floating-point register rename map */ 1559919Ssteve.reinhardt@amd.com SimpleRenameMap floatMap; 1569919Ssteve.reinhardt@amd.com 1579919Ssteve.reinhardt@amd.com /** 1589919Ssteve.reinhardt@amd.com * The register file object is used only to distinguish integer 1599919Ssteve.reinhardt@amd.com * from floating-point physical register indices, which in turn is 1609919Ssteve.reinhardt@amd.com * used only for assert statements that make sure the physical 1619919Ssteve.reinhardt@amd.com * register indices that get passed in and handed out are of the 1629919Ssteve.reinhardt@amd.com * proper class. 1639919Ssteve.reinhardt@amd.com */ 1649919Ssteve.reinhardt@amd.com PhysRegFile *regFile; 1659919Ssteve.reinhardt@amd.com 1669920Syasuko.eckert@amd.com /** The condition-code register rename map */ 1679920Syasuko.eckert@amd.com SimpleRenameMap ccMap; 1689920Syasuko.eckert@amd.com 1691060SN/A public: 1709919Ssteve.reinhardt@amd.com typedef TheISA::RegIndex RegIndex; 1719919Ssteve.reinhardt@amd.com 1729919Ssteve.reinhardt@amd.com typedef SimpleRenameMap::RenameInfo RenameInfo; 1739919Ssteve.reinhardt@amd.com 1742348SN/A /** Default constructor. init() must be called prior to use. */ 17510537Sandreas.hansson@arm.com UnifiedRenameMap() : regFile(nullptr) {}; 1761060SN/A 1771061SN/A /** Destructor. */ 1789919Ssteve.reinhardt@amd.com ~UnifiedRenameMap() {}; 1791061SN/A 1802348SN/A /** Initializes rename map with given parameters. */ 1819919Ssteve.reinhardt@amd.com void init(PhysRegFile *_regFile, 1822292SN/A RegIndex _intZeroReg, 1832292SN/A RegIndex _floatZeroReg, 1849919Ssteve.reinhardt@amd.com UnifiedFreeList *freeList); 1852292SN/A 1869919Ssteve.reinhardt@amd.com /** 1879919Ssteve.reinhardt@amd.com * Tell rename map to get a new free physical register to remap 1889919Ssteve.reinhardt@amd.com * the specified architectural register. This version takes a 1899919Ssteve.reinhardt@amd.com * unified flattened architectural register index and calls the 1909919Ssteve.reinhardt@amd.com * appropriate class-specific rename table. 1919919Ssteve.reinhardt@amd.com * @param arch_reg The unified architectural register index to remap. 1929919Ssteve.reinhardt@amd.com * @return A RenameInfo pair indicating both the new and previous 1939919Ssteve.reinhardt@amd.com * physical registers. 1949919Ssteve.reinhardt@amd.com */ 1951060SN/A RenameInfo rename(RegIndex arch_reg); 1961060SN/A 1979919Ssteve.reinhardt@amd.com /** 1989919Ssteve.reinhardt@amd.com * Perform rename() on an integer register, given a relative 1999919Ssteve.reinhardt@amd.com * integer register index. 2009919Ssteve.reinhardt@amd.com */ 2019919Ssteve.reinhardt@amd.com RenameInfo renameInt(RegIndex rel_arch_reg) 2029919Ssteve.reinhardt@amd.com { 2039919Ssteve.reinhardt@amd.com RenameInfo info = intMap.rename(rel_arch_reg); 2049919Ssteve.reinhardt@amd.com assert(regFile->isIntPhysReg(info.first)); 2059919Ssteve.reinhardt@amd.com return info; 2069919Ssteve.reinhardt@amd.com } 2071060SN/A 2081060SN/A /** 2099919Ssteve.reinhardt@amd.com * Perform rename() on a floating-point register, given a relative 2109919Ssteve.reinhardt@amd.com * floating-point register index. 2111060SN/A */ 2129919Ssteve.reinhardt@amd.com RenameInfo renameFloat(RegIndex rel_arch_reg) 2139919Ssteve.reinhardt@amd.com { 2149919Ssteve.reinhardt@amd.com RenameInfo info = floatMap.rename(rel_arch_reg); 2159919Ssteve.reinhardt@amd.com assert(regFile->isFloatPhysReg(info.first)); 2169919Ssteve.reinhardt@amd.com return info; 2179919Ssteve.reinhardt@amd.com } 2181060SN/A 2199919Ssteve.reinhardt@amd.com /** 2209920Syasuko.eckert@amd.com * Perform rename() on a condition-code register, given a relative 2219920Syasuko.eckert@amd.com * condition-code register index. 2229920Syasuko.eckert@amd.com */ 2239920Syasuko.eckert@amd.com RenameInfo renameCC(RegIndex rel_arch_reg) 2249920Syasuko.eckert@amd.com { 2259920Syasuko.eckert@amd.com RenameInfo info = ccMap.rename(rel_arch_reg); 2269920Syasuko.eckert@amd.com assert(regFile->isCCPhysReg(info.first)); 2279920Syasuko.eckert@amd.com return info; 2289920Syasuko.eckert@amd.com } 2299920Syasuko.eckert@amd.com 2309920Syasuko.eckert@amd.com /** 2319919Ssteve.reinhardt@amd.com * Perform rename() on a misc register, given a relative 2329919Ssteve.reinhardt@amd.com * misc register index. 2339919Ssteve.reinhardt@amd.com */ 2349919Ssteve.reinhardt@amd.com RenameInfo renameMisc(RegIndex rel_arch_reg) 2359919Ssteve.reinhardt@amd.com { 2369919Ssteve.reinhardt@amd.com // misc regs aren't really renamed, just remapped 2379919Ssteve.reinhardt@amd.com PhysRegIndex phys_reg = lookupMisc(rel_arch_reg); 2389919Ssteve.reinhardt@amd.com // Set the previous register to the same register; mainly it must be 2399919Ssteve.reinhardt@amd.com // known that the prev reg was outside the range of normal registers 2409919Ssteve.reinhardt@amd.com // so the free list can avoid adding it. 2419919Ssteve.reinhardt@amd.com return RenameInfo(phys_reg, phys_reg); 2429919Ssteve.reinhardt@amd.com } 2431060SN/A 2442292SN/A 2459919Ssteve.reinhardt@amd.com /** 2469919Ssteve.reinhardt@amd.com * Look up the physical register mapped to an architectural register. 2479919Ssteve.reinhardt@amd.com * This version takes a unified flattened architectural register index 2489919Ssteve.reinhardt@amd.com * and calls the appropriate class-specific rename table. 2499919Ssteve.reinhardt@amd.com * @param arch_reg The unified architectural register to look up. 2509919Ssteve.reinhardt@amd.com * @return The physical register it is currently mapped to. 2519919Ssteve.reinhardt@amd.com */ 2529919Ssteve.reinhardt@amd.com PhysRegIndex lookup(RegIndex arch_reg) const; 2531060SN/A 2549919Ssteve.reinhardt@amd.com /** 2559919Ssteve.reinhardt@amd.com * Perform lookup() on an integer register, given a relative 2569919Ssteve.reinhardt@amd.com * integer register index. 2579919Ssteve.reinhardt@amd.com */ 2589919Ssteve.reinhardt@amd.com PhysRegIndex lookupInt(RegIndex rel_arch_reg) const 2599919Ssteve.reinhardt@amd.com { 2609919Ssteve.reinhardt@amd.com PhysRegIndex phys_reg = intMap.lookup(rel_arch_reg); 2619919Ssteve.reinhardt@amd.com assert(regFile->isIntPhysReg(phys_reg)); 2629919Ssteve.reinhardt@amd.com return phys_reg; 2639919Ssteve.reinhardt@amd.com } 2641060SN/A 2659919Ssteve.reinhardt@amd.com /** 2669919Ssteve.reinhardt@amd.com * Perform lookup() on a floating-point register, given a relative 2679919Ssteve.reinhardt@amd.com * floating-point register index. 2689919Ssteve.reinhardt@amd.com */ 2699919Ssteve.reinhardt@amd.com PhysRegIndex lookupFloat(RegIndex rel_arch_reg) const 2709919Ssteve.reinhardt@amd.com { 2719919Ssteve.reinhardt@amd.com PhysRegIndex phys_reg = floatMap.lookup(rel_arch_reg); 2729919Ssteve.reinhardt@amd.com assert(regFile->isFloatPhysReg(phys_reg)); 2739919Ssteve.reinhardt@amd.com return phys_reg; 2749919Ssteve.reinhardt@amd.com } 2751060SN/A 2769919Ssteve.reinhardt@amd.com /** 2779920Syasuko.eckert@amd.com * Perform lookup() on a condition-code register, given a relative 2789920Syasuko.eckert@amd.com * condition-code register index. 2799920Syasuko.eckert@amd.com */ 2809920Syasuko.eckert@amd.com PhysRegIndex lookupCC(RegIndex rel_arch_reg) const 2819920Syasuko.eckert@amd.com { 2829920Syasuko.eckert@amd.com PhysRegIndex phys_reg = ccMap.lookup(rel_arch_reg); 2839920Syasuko.eckert@amd.com assert(regFile->isCCPhysReg(phys_reg)); 2849920Syasuko.eckert@amd.com return phys_reg; 2859920Syasuko.eckert@amd.com } 2869920Syasuko.eckert@amd.com 2879920Syasuko.eckert@amd.com /** 2889919Ssteve.reinhardt@amd.com * Perform lookup() on a misc register, given a relative 2899919Ssteve.reinhardt@amd.com * misc register index. 2909919Ssteve.reinhardt@amd.com */ 2919919Ssteve.reinhardt@amd.com PhysRegIndex lookupMisc(RegIndex rel_arch_reg) const 2929919Ssteve.reinhardt@amd.com { 2939919Ssteve.reinhardt@amd.com // misc regs aren't really renamed, just given an index 2949919Ssteve.reinhardt@amd.com // beyond the range of actual physical registers 2959919Ssteve.reinhardt@amd.com PhysRegIndex phys_reg = rel_arch_reg + regFile->totalNumPhysRegs(); 2969919Ssteve.reinhardt@amd.com return phys_reg; 2979919Ssteve.reinhardt@amd.com } 2981060SN/A 2999919Ssteve.reinhardt@amd.com /** 3009919Ssteve.reinhardt@amd.com * Update rename map with a specific mapping. Generally used to 3019919Ssteve.reinhardt@amd.com * roll back to old mappings on a squash. This version takes a 3029919Ssteve.reinhardt@amd.com * unified flattened architectural register index and calls the 3039919Ssteve.reinhardt@amd.com * appropriate class-specific rename table. 3049919Ssteve.reinhardt@amd.com * @param arch_reg The unified architectural register to remap. 3059919Ssteve.reinhardt@amd.com * @param phys_reg The physical register to remap it to. 3069919Ssteve.reinhardt@amd.com */ 3079919Ssteve.reinhardt@amd.com void setEntry(RegIndex arch_reg, PhysRegIndex phys_reg); 3081060SN/A 3099919Ssteve.reinhardt@amd.com /** 3109919Ssteve.reinhardt@amd.com * Perform setEntry() on an integer register, given a relative 3119919Ssteve.reinhardt@amd.com * integer register index. 3129919Ssteve.reinhardt@amd.com */ 3139919Ssteve.reinhardt@amd.com void setIntEntry(RegIndex arch_reg, PhysRegIndex phys_reg) 3149919Ssteve.reinhardt@amd.com { 3159919Ssteve.reinhardt@amd.com assert(regFile->isIntPhysReg(phys_reg)); 3169919Ssteve.reinhardt@amd.com intMap.setEntry(arch_reg, phys_reg); 3179919Ssteve.reinhardt@amd.com } 3181060SN/A 3199919Ssteve.reinhardt@amd.com /** 3209919Ssteve.reinhardt@amd.com * Perform setEntry() on a floating-point register, given a relative 3219919Ssteve.reinhardt@amd.com * floating-point register index. 3229919Ssteve.reinhardt@amd.com */ 3239919Ssteve.reinhardt@amd.com void setFloatEntry(RegIndex arch_reg, PhysRegIndex phys_reg) 3249919Ssteve.reinhardt@amd.com { 3259919Ssteve.reinhardt@amd.com assert(regFile->isFloatPhysReg(phys_reg)); 3269919Ssteve.reinhardt@amd.com floatMap.setEntry(arch_reg, phys_reg); 3279919Ssteve.reinhardt@amd.com } 3281060SN/A 3299919Ssteve.reinhardt@amd.com /** 3309920Syasuko.eckert@amd.com * Perform setEntry() on a condition-code register, given a relative 3319920Syasuko.eckert@amd.com * condition-code register index. 3329920Syasuko.eckert@amd.com */ 3339920Syasuko.eckert@amd.com void setCCEntry(RegIndex arch_reg, PhysRegIndex phys_reg) 3349920Syasuko.eckert@amd.com { 3359920Syasuko.eckert@amd.com assert(regFile->isCCPhysReg(phys_reg)); 3369920Syasuko.eckert@amd.com ccMap.setEntry(arch_reg, phys_reg); 3379920Syasuko.eckert@amd.com } 3389920Syasuko.eckert@amd.com 3399920Syasuko.eckert@amd.com /** 3409919Ssteve.reinhardt@amd.com * Return the minimum number of free entries across all of the 3419919Ssteve.reinhardt@amd.com * register classes. The minimum is used so we guarantee that 3429919Ssteve.reinhardt@amd.com * this number of entries is available regardless of which class 3439919Ssteve.reinhardt@amd.com * of registers is requested. 3441060SN/A */ 3459919Ssteve.reinhardt@amd.com unsigned numFreeEntries() const 3461060SN/A { 3479919Ssteve.reinhardt@amd.com return std::min(intMap.numFreeEntries(), floatMap.numFreeEntries()); 3489919Ssteve.reinhardt@amd.com } 3491060SN/A}; 3501060SN/A 3512292SN/A#endif //__CPU_O3_RENAME_MAP_HH__ 352