rename_map.hh revision 9920
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. */
1759919Ssteve.reinhardt@amd.com    UnifiedRenameMap() {};
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