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