From: Nathanael Premillieu Date: Wed, 5 Apr 2017 17:46:06 +0000 (-0500) Subject: cpu: Physical register structural + flat indexing X-Git-Tag: v19.0.0.0~2714 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=43d833246fcfe092a0c08dde1fdf7e3d409d1af9;p=gem5.git cpu: Physical register structural + flat indexing Mimic the changes done on the architectural register indexes on the physical register indexes. This is specific to the O3 model. The structure, called PhysRegId, contains a register class, a register index and a flat register index. The flat register index is kept because it is useful in some cases where the type of register is not important (dependency graph and scoreboard for example). Instead of directly using the structure, most of the code is working with a const PhysRegId* (typedef to PhysRegIdPtr). The actual PhysRegId objects are stored in the regFile. Change-Id: Ic879a3cc608aa2f34e2168280faac1846de77667 Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/2701 Reviewed-by: Anthony Gutierrez Maintainer: Andreas Sandberg --- diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 84a6540af..369d7a02a 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -267,17 +267,17 @@ class BaseDynInst : public ExecContext, public RefCounted /** Physical register index of the destination registers of this * instruction. */ - std::array _destRegIdx; + std::array _destRegIdx; /** Physical register index of the source registers of this * instruction. */ - std::array _srcRegIdx; + std::array _srcRegIdx; /** Physical register index of the previous producers of the * architected destinations. */ - std::array _prevDestRegIdx; + std::array _prevDestRegIdx; public: @@ -368,13 +368,13 @@ class BaseDynInst : public ExecContext, public RefCounted /** Returns the physical register index of the i'th destination * register. */ - PhysRegIndex renamedDestRegIdx(int idx) const + PhysRegIdPtr renamedDestRegIdx(int idx) const { return _destRegIdx[idx]; } /** Returns the physical register index of the i'th source register. */ - PhysRegIndex renamedSrcRegIdx(int idx) const + PhysRegIdPtr renamedSrcRegIdx(int idx) const { assert(TheISA::MaxInstSrcRegs > idx); return _srcRegIdx[idx]; @@ -391,7 +391,7 @@ class BaseDynInst : public ExecContext, public RefCounted /** Returns the physical register index of the previous physical register * that remapped to the same logical register index. */ - PhysRegIndex prevDestRegIdx(int idx) const + PhysRegIdPtr prevDestRegIdx(int idx) const { return _prevDestRegIdx[idx]; } @@ -400,8 +400,8 @@ class BaseDynInst : public ExecContext, public RefCounted * the previous physical register that the logical register mapped to. */ void renameDestReg(int idx, - PhysRegIndex renamed_dest, - PhysRegIndex previous_rename) + PhysRegIdPtr renamed_dest, + PhysRegIdPtr previous_rename) { _destRegIdx[idx] = renamed_dest; _prevDestRegIdx[idx] = previous_rename; @@ -411,7 +411,7 @@ class BaseDynInst : public ExecContext, public RefCounted * has/will produce that logical register's result. * @todo: add in whether or not the source register is ready. */ - void renameSrcReg(int idx, PhysRegIndex renamed_src) + void renameSrcReg(int idx, PhysRegIdPtr renamed_src) { _srcRegIdx[idx] = renamed_src; } diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index 4da251104..c5f1c0144 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * @@ -39,6 +39,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim + * Nathanael Premillieu */ #ifndef __CPU_O3_COMM_HH__ @@ -55,6 +56,57 @@ // most likely location for this, there are a few classes that need this // typedef yet are not templated on the Impl. For now it will be defined here. typedef short int PhysRegIndex; +// Physical register ID +// Associate a physical register index to a register class and +// so it is easy to track which type of register are used. +// A flat index is also provided for when it is useful to have a unified +// indexing (for the dependency graph and the scoreboard for example) +struct PhysRegId { + RegClass regClass; + PhysRegIndex regIdx; + PhysRegIndex flatIdx; + PhysRegId(RegClass _regClass, PhysRegIndex _regIdx, + PhysRegIndex _flatIdx) + : regClass(_regClass), regIdx(_regIdx), flatIdx(_flatIdx) + {} + + bool operator==(const PhysRegId& that) const { + return regClass == that.regClass && regIdx == that.regIdx; + } + + bool operator!=(const PhysRegId& that) const { + return !(*this==that); + } + + bool isZeroReg() const + { + return (regIdx == TheISA::ZeroReg && + (regClass == IntRegClass || + (THE_ISA == ALPHA_ISA && regClass == FloatRegClass))); + } + + /** @return true if it is an integer physical register. */ + bool isIntPhysReg() const { return regClass == IntRegClass; } + + /** @return true if it is a floating-point physical register. */ + bool isFloatPhysReg() const { return regClass == FloatRegClass; } + + /** @Return true if it is a condition-code physical register. */ + bool isCCPhysReg() const { return regClass == CCRegClass; } + + /** + * Returns true if this register is always associated to the same + * architectural register. + */ + bool isFixedMapping() const + { + return regClass == MiscRegClass; + } +}; + +// PhysRegIds only need to be created once and then we can use the following +// to work with them +typedef const PhysRegId* PhysRegIdPtr; /** Struct that defines the information passed from fetch to decode. */ template diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index a2d8147ea..6e9accdd5 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -180,8 +180,7 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) rob(this, params), scoreboard(name() + ".scoreboard", - regFile.totalNumPhysRegs(), TheISA::NumMiscRegs, - TheISA::ZeroReg, TheISA::ZeroReg), + regFile.totalNumPhysRegs()), isa(numThreads, NULL), @@ -300,19 +299,19 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { // Note that we can't use the rename() method because we don't // want special treatment for the zero register at this point - PhysRegIndex phys_reg = freeList.getIntReg(); + PhysRegIdPtr phys_reg = freeList.getIntReg(); renameMap[tid].setIntEntry(ridx, phys_reg); commitRenameMap[tid].setIntEntry(ridx, phys_reg); } for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { - PhysRegIndex phys_reg = freeList.getFloatReg(); + PhysRegIdPtr phys_reg = freeList.getFloatReg(); renameMap[tid].setFloatEntry(ridx, phys_reg); commitRenameMap[tid].setFloatEntry(ridx, phys_reg); } for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { - PhysRegIndex phys_reg = freeList.getCCReg(); + PhysRegIdPtr phys_reg = freeList.getCCReg(); renameMap[tid].setCCEntry(ridx, phys_reg); commitRenameMap[tid].setCCEntry(ridx, phys_reg); } @@ -791,7 +790,7 @@ FullO3CPU::insertThread(ThreadID tid) for (RegId reg_id(IntRegClass, 0); reg_id.regIdx < TheISA::NumIntRegs; reg_id.regIdx++) { - PhysRegIndex phys_reg = freeList.getIntReg(); + PhysRegIdPtr phys_reg = freeList.getIntReg(); renameMap[tid].setEntry(reg_id, phys_reg); scoreboard.setReg(phys_reg); } @@ -799,7 +798,7 @@ FullO3CPU::insertThread(ThreadID tid) //Bind Float Regs to Rename Map for (RegId reg_id(FloatRegClass, 0); reg_id.regIdx < TheISA::NumFloatRegs; reg_id.regIdx++) { - PhysRegIndex phys_reg = freeList.getFloatReg(); + PhysRegIdPtr phys_reg = freeList.getFloatReg(); renameMap[tid].setEntry(reg_id, phys_reg); scoreboard.setReg(phys_reg); } @@ -807,7 +806,7 @@ FullO3CPU::insertThread(ThreadID tid) //Bind condition-code Regs to Rename Map for (RegId reg_id(CCRegClass, 0); reg_id.regIdx < TheISA::NumCCRegs; reg_id.regIdx++) { - PhysRegIndex phys_reg = freeList.getCCReg(); + PhysRegIdPtr phys_reg = freeList.getCCReg(); renameMap[tid].setEntry(reg_id, phys_reg); scoreboard.setReg(phys_reg); } @@ -845,7 +844,7 @@ FullO3CPU::removeThread(ThreadID tid) // Unbind Int Regs from Rename Map for (RegId reg_id(IntRegClass, 0); reg_id.regIdx < TheISA::NumIntRegs; reg_id.regIdx++) { - PhysRegIndex phys_reg = renameMap[tid].lookup(reg_id); + PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id); scoreboard.unsetReg(phys_reg); freeList.addReg(phys_reg); } @@ -853,7 +852,7 @@ FullO3CPU::removeThread(ThreadID tid) // Unbind Float Regs from Rename Map for (RegId reg_id(FloatRegClass, 0); reg_id.regIdx < TheISA::NumFloatRegs; reg_id.regIdx++) { - PhysRegIndex phys_reg = renameMap[tid].lookup(reg_id); + PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id); scoreboard.unsetReg(phys_reg); freeList.addReg(phys_reg); } @@ -861,7 +860,7 @@ FullO3CPU::removeThread(ThreadID tid) // Unbind condition-code Regs from Rename Map for (RegId reg_id(CCRegClass, 0); reg_id.regIdx < TheISA::NumCCRegs; reg_id.regIdx++) { - PhysRegIndex phys_reg = renameMap[tid].lookup(reg_id); + PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id); scoreboard.unsetReg(phys_reg); freeList.addReg(phys_reg); } @@ -1234,66 +1233,66 @@ FullO3CPU::setMiscReg(int misc_reg, template uint64_t -FullO3CPU::readIntReg(int reg_idx) +FullO3CPU::readIntReg(PhysRegIdPtr phys_reg) { intRegfileReads++; - return regFile.readIntReg(reg_idx); + return regFile.readIntReg(phys_reg); } template FloatReg -FullO3CPU::readFloatReg(int reg_idx) +FullO3CPU::readFloatReg(PhysRegIdPtr phys_reg) { fpRegfileReads++; - return regFile.readFloatReg(reg_idx); + return regFile.readFloatReg(phys_reg); } template FloatRegBits -FullO3CPU::readFloatRegBits(int reg_idx) +FullO3CPU::readFloatRegBits(PhysRegIdPtr phys_reg) { fpRegfileReads++; - return regFile.readFloatRegBits(reg_idx); + return regFile.readFloatRegBits(phys_reg); } template CCReg -FullO3CPU::readCCReg(int reg_idx) +FullO3CPU::readCCReg(PhysRegIdPtr phys_reg) { ccRegfileReads++; - return regFile.readCCReg(reg_idx); + return regFile.readCCReg(phys_reg); } template void -FullO3CPU::setIntReg(int reg_idx, uint64_t val) +FullO3CPU::setIntReg(PhysRegIdPtr phys_reg, uint64_t val) { intRegfileWrites++; - regFile.setIntReg(reg_idx, val); + regFile.setIntReg(phys_reg, val); } template void -FullO3CPU::setFloatReg(int reg_idx, FloatReg val) +FullO3CPU::setFloatReg(PhysRegIdPtr phys_reg, FloatReg val) { fpRegfileWrites++; - regFile.setFloatReg(reg_idx, val); + regFile.setFloatReg(phys_reg, val); } template void -FullO3CPU::setFloatRegBits(int reg_idx, FloatRegBits val) +FullO3CPU::setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val) { fpRegfileWrites++; - regFile.setFloatRegBits(reg_idx, val); + regFile.setFloatRegBits(phys_reg, val); } template void -FullO3CPU::setCCReg(int reg_idx, CCReg val) +FullO3CPU::setCCReg(PhysRegIdPtr phys_reg, CCReg val) { ccRegfileWrites++; - regFile.setCCReg(reg_idx, val); + regFile.setCCReg(phys_reg, val); } template @@ -1301,7 +1300,7 @@ uint64_t FullO3CPU::readArchIntReg(int reg_idx, ThreadID tid) { intRegfileReads++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupInt(reg_idx); return regFile.readIntReg(phys_reg); } @@ -1311,7 +1310,7 @@ float FullO3CPU::readArchFloatReg(int reg_idx, ThreadID tid) { fpRegfileReads++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); return regFile.readFloatReg(phys_reg); } @@ -1321,7 +1320,7 @@ uint64_t FullO3CPU::readArchFloatRegInt(int reg_idx, ThreadID tid) { fpRegfileReads++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); return regFile.readFloatRegBits(phys_reg); } @@ -1331,7 +1330,7 @@ CCReg FullO3CPU::readArchCCReg(int reg_idx, ThreadID tid) { ccRegfileReads++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupCC(reg_idx); return regFile.readCCReg(phys_reg); } @@ -1341,7 +1340,7 @@ void FullO3CPU::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) { intRegfileWrites++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupInt(reg_idx); regFile.setIntReg(phys_reg, val); } @@ -1351,7 +1350,7 @@ void FullO3CPU::setArchFloatReg(int reg_idx, float val, ThreadID tid) { fpRegfileWrites++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); regFile.setFloatReg(phys_reg, val); } @@ -1361,7 +1360,7 @@ void FullO3CPU::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) { fpRegfileWrites++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); regFile.setFloatRegBits(phys_reg, val); } @@ -1371,7 +1370,7 @@ void FullO3CPU::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) { ccRegfileWrites++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); + PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupCC(reg_idx); regFile.setCCReg(phys_reg, val); } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index abe036b09..b5cbc5fe2 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -411,21 +411,21 @@ class FullO3CPU : public BaseO3CPU void setMiscReg(int misc_reg, const TheISA::MiscReg &val, ThreadID tid); - uint64_t readIntReg(int reg_idx); + uint64_t readIntReg(PhysRegIdPtr phys_reg); - TheISA::FloatReg readFloatReg(int reg_idx); + TheISA::FloatReg readFloatReg(PhysRegIdPtr phys_reg); - TheISA::FloatRegBits readFloatRegBits(int reg_idx); + TheISA::FloatRegBits readFloatRegBits(PhysRegIdPtr phys_reg); - TheISA::CCReg readCCReg(int reg_idx); + TheISA::CCReg readCCReg(PhysRegIdPtr phys_reg); - void setIntReg(int reg_idx, uint64_t val); + void setIntReg(PhysRegIdPtr phys_reg, uint64_t val); - void setFloatReg(int reg_idx, TheISA::FloatReg val); + void setFloatReg(PhysRegIdPtr phys_reg, TheISA::FloatReg val); - void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val); + void setFloatRegBits(PhysRegIdPtr phys_reg, TheISA::FloatRegBits val); - void setCCReg(int reg_idx, TheISA::CCReg val); + void setCCReg(PhysRegIdPtr phys_reg, TheISA::CCReg val); uint64_t readArchIntReg(int reg_idx, ThreadID tid); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 3096e5946..b200a328a 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -207,7 +207,7 @@ class BaseO3DynInst : public BaseDynInst { for (int idx = 0; idx < this->numDestRegs(); idx++) { - PhysRegIndex prev_phys_reg = this->prevDestRegIdx(idx); + PhysRegIdPtr prev_phys_reg = this->prevDestRegIdx(idx); RegId original_dest_reg = this->staticInst->destRegIdx(idx); switch (original_dest_reg.regClass) { diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index f6a42c398..03437a5ae 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -106,17 +106,6 @@ template void BaseO3DynInst::initVars() { - // Make sure to have the renamed register entries set to the same - // as the normal register entries. It will allow the IQ to work - // without any modifications. - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - this->_destRegIdx[i] = this->staticInst->destRegIdx(i).regIdx; - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i).regIdx; - } - this->_readySrcRegIdx.reset(); _numDestMiscRegs = 0; diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh index aa805e26e..3e6740e57 100644 --- a/src/cpu/o3/free_list.hh +++ b/src/cpu/o3/free_list.hh @@ -34,6 +34,7 @@ #include #include +#include #include "base/misc.hh" #include "base/trace.hh" @@ -53,20 +54,20 @@ class SimpleFreeList private: /** The actual free list */ - std::queue freeRegs; + std::queue freeRegs; public: SimpleFreeList() {}; /** Add a physical register to the free list */ - void addReg(PhysRegIndex reg) { freeRegs.push(reg); } + void addReg(PhysRegIdPtr reg) { freeRegs.push(reg); } /** Get the next available register from the free list */ - PhysRegIndex getReg() + PhysRegIdPtr getReg() { assert(!freeRegs.empty()); - PhysRegIndex free_reg = freeRegs.front(); + PhysRegIdPtr free_reg = freeRegs.front(); freeRegs.pop(); return free_reg; } @@ -140,25 +141,25 @@ class UnifiedFreeList SimpleFreeList *getCCList() { return &ccList; } /** Gets a free integer register. */ - PhysRegIndex getIntReg() { return intList.getReg(); } + PhysRegIdPtr getIntReg() { return intList.getReg(); } /** Gets a free fp register. */ - PhysRegIndex getFloatReg() { return floatList.getReg(); } + PhysRegIdPtr getFloatReg() { return floatList.getReg(); } /** Gets a free cc register. */ - PhysRegIndex getCCReg() { return ccList.getReg(); } + PhysRegIdPtr getCCReg() { return ccList.getReg(); } /** Adds a register back to the free list. */ - void addReg(PhysRegIndex freed_reg); + void addReg(PhysRegIdPtr freed_reg); /** Adds an integer register back to the free list. */ - void addIntReg(PhysRegIndex freed_reg) { intList.addReg(freed_reg); } + void addIntReg(PhysRegIdPtr freed_reg) { intList.addReg(freed_reg); } /** Adds a fp register back to the free list. */ - void addFloatReg(PhysRegIndex freed_reg) { floatList.addReg(freed_reg); } + void addFloatReg(PhysRegIdPtr freed_reg) { floatList.addReg(freed_reg); } /** Adds a cc register back to the free list. */ - void addCCReg(PhysRegIndex freed_reg) { ccList.addReg(freed_reg); } + void addCCReg(PhysRegIdPtr freed_reg) { ccList.addReg(freed_reg); } /** Checks if there are any free integer registers. */ bool hasFreeIntRegs() const { return intList.hasFreeRegs(); } @@ -180,18 +181,25 @@ class UnifiedFreeList }; inline void -UnifiedFreeList::addReg(PhysRegIndex freed_reg) +UnifiedFreeList::addReg(PhysRegIdPtr freed_reg) { - DPRINTF(FreeList,"Freeing register %i.\n", freed_reg); + DPRINTF(FreeList,"Freeing register %i (%s).\n", freed_reg->regIdx, + RegClassStrings[freed_reg->regClass]); //Might want to add in a check for whether or not this register is //already in there. A bit vector or something similar would be useful. - if (regFile->isIntPhysReg(freed_reg)) { - intList.addReg(freed_reg); - } else if (regFile->isFloatPhysReg(freed_reg)) { - floatList.addReg(freed_reg); - } else { - assert(regFile->isCCPhysReg(freed_reg)); - ccList.addReg(freed_reg); + switch (freed_reg->regClass) { + case IntRegClass: + intList.addReg(freed_reg); + break; + case FloatRegClass: + floatList.addReg(freed_reg); + break; + case CCRegClass: + ccList.addReg(freed_reg); + break; + default: + panic("Unexpected RegClass (%s)", + RegClassStrings[freed_reg->regClass]); } // These assert conditions ensure that the number of free diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 78b83eba6..cdb6b26e2 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -1433,8 +1433,9 @@ DefaultIEW::writebackInsts() for (int i = 0; i < inst->numDestRegs(); i++) { //mark as Ready - DPRINTF(IEW,"Setting Destination Register %i\n", - inst->renamedDestRegIdx(i)); + DPRINTF(IEW,"Setting Destination Register %i (%s)\n", + inst->renamedDestRegIdx(i)->regIdx, + RegClassStrings[inst->renamedDestRegIdx(i)->regClass]); scoreboard->setReg(inst->renamedDestRegIdx(i)); } diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 7352c622b..c46fd6ba7 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -979,24 +979,24 @@ InstructionQueue::wakeDependents(DynInstPtr &completed_inst) dest_reg_idx < completed_inst->numDestRegs(); dest_reg_idx++) { - PhysRegIndex dest_reg = + PhysRegIdPtr dest_reg = completed_inst->renamedDestRegIdx(dest_reg_idx); // Special case of uniq or control registers. They are not // handled by the IQ and thus have no dependency graph entry. - // @todo Figure out a cleaner way to handle this. - if (dest_reg >= numPhysRegs) { - DPRINTF(IQ, "dest_reg :%d, numPhysRegs: %d\n", dest_reg, - numPhysRegs); + if (dest_reg->isFixedMapping()) { + DPRINTF(IQ, "Reg %d [%s] is part of a fix mapping, skipping\n", + dest_reg->regIdx, RegClassStrings[dest_reg->regClass]); continue; } - DPRINTF(IQ, "Waking any dependents on register %i.\n", - (int) dest_reg); + DPRINTF(IQ, "Waking any dependents on register %i (%s).\n", + dest_reg->regIdx, + RegClassStrings[dest_reg->regClass]); //Go through the dependency chain, marking the registers as //ready within the waiting instructions. - DynInstPtr dep_inst = dependGraph.pop(dest_reg); + DynInstPtr dep_inst = dependGraph.pop(dest_reg->flatIdx); while (dep_inst) { DPRINTF(IQ, "Waking up a dependent instruction, [sn:%lli] " @@ -1010,18 +1010,18 @@ InstructionQueue::wakeDependents(DynInstPtr &completed_inst) addIfReady(dep_inst); - dep_inst = dependGraph.pop(dest_reg); + dep_inst = dependGraph.pop(dest_reg->flatIdx); ++dependents; } // Reset the head node now that all of its dependents have // been woken up. - assert(dependGraph.empty(dest_reg)); - dependGraph.clearInst(dest_reg); + assert(dependGraph.empty(dest_reg->flatIdx)); + dependGraph.clearInst(dest_reg->flatIdx); // Mark the scoreboard as having that register ready. - regScoreboard[dest_reg] = true; + regScoreboard[dest_reg->flatIdx] = true; } return dependents; } @@ -1219,7 +1219,7 @@ InstructionQueue::doSquash(ThreadID tid) src_reg_idx < squashed_inst->numSrcRegs(); src_reg_idx++) { - PhysRegIndex src_reg = + PhysRegIdPtr src_reg = squashed_inst->renamedSrcRegIdx(src_reg_idx); // Only remove it from the dependency graph if it @@ -1232,8 +1232,8 @@ InstructionQueue::doSquash(ThreadID tid) // leaves more room for error. if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) && - src_reg < numPhysRegs) { - dependGraph.remove(src_reg, squashed_inst); + !src_reg->isFixedMapping()) { + dependGraph.remove(src_reg->flatIdx, squashed_inst); } @@ -1300,28 +1300,30 @@ InstructionQueue::addToDependents(DynInstPtr &new_inst) { // Only add it to the dependency graph if it's not ready. if (!new_inst->isReadySrcRegIdx(src_reg_idx)) { - PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx); + PhysRegIdPtr src_reg = new_inst->renamedSrcRegIdx(src_reg_idx); // Check the IQ's scoreboard to make sure the register // hasn't become ready while the instruction was in flight // between stages. Only if it really isn't ready should // it be added to the dependency graph. - if (src_reg >= numPhysRegs) { + if (src_reg->isFixedMapping()) { continue; - } else if (!regScoreboard[src_reg]) { - DPRINTF(IQ, "Instruction PC %s has src reg %i that " + } else if (!regScoreboard[src_reg->flatIdx]) { + DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that " "is being added to the dependency chain.\n", - new_inst->pcState(), src_reg); + new_inst->pcState(), src_reg->regIdx, + RegClassStrings[src_reg->regClass]); - dependGraph.insert(src_reg, new_inst); + dependGraph.insert(src_reg->flatIdx, new_inst); // Change the return value to indicate that something // was added to the dependency graph. return_val = true; } else { - DPRINTF(IQ, "Instruction PC %s has src reg %i that " + DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that " "became ready before it reached the IQ.\n", - new_inst->pcState(), src_reg); + new_inst->pcState(), src_reg->regIdx, + RegClassStrings[src_reg->regClass]); // Mark a register ready within the instruction. new_inst->markSrcRegReady(src_reg_idx); } @@ -1345,25 +1347,25 @@ InstructionQueue::addToProducers(DynInstPtr &new_inst) dest_reg_idx < total_dest_regs; dest_reg_idx++) { - PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx); + PhysRegIdPtr dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx); - // Instructions that use the misc regs will have a reg number - // higher than the normal physical registers. In this case these - // registers are not renamed, and there is no need to track + // Some registers have fixed mapping, and there is no need to track // dependencies as these instructions must be executed at commit. - if (dest_reg >= numPhysRegs) { + if (dest_reg->isFixedMapping()) { continue; } - if (!dependGraph.empty(dest_reg)) { + if (!dependGraph.empty(dest_reg->flatIdx)) { dependGraph.dump(); - panic("Dependency graph %i not empty!", dest_reg); + panic("Dependency graph %i (%s) (flat: %i) not empty!", + dest_reg->regIdx, RegClassStrings[dest_reg->regClass], + dest_reg->flatIdx); } - dependGraph.setInst(dest_reg, new_inst); + dependGraph.setInst(dest_reg->flatIdx, new_inst); // Mark the scoreboard to say it's not yet ready. - regScoreboard[dest_reg] = false; + regScoreboard[dest_reg->flatIdx] = false; } } diff --git a/src/cpu/o3/probe/elastic_trace.cc b/src/cpu/o3/probe/elastic_trace.cc index 05b16805f..76f7e439a 100644 --- a/src/cpu/o3/probe/elastic_trace.cc +++ b/src/cpu/o3/probe/elastic_trace.cc @@ -239,10 +239,11 @@ ElasticTrace::updateRegDep(const DynInstPtr &dyn_inst) int8_t max_regs = dyn_inst->numSrcRegs(); for (int src_idx = 0; src_idx < max_regs; src_idx++) { // Get the physical register index of the i'th source register. - PhysRegIndex src_reg = dyn_inst->renamedSrcRegIdx(src_idx); - DPRINTFR(ElasticTrace, "[sn:%lli] Check map for src reg %i\n", seq_num, - src_reg); - auto itr_last_writer = physRegDepMap.find(src_reg); + PhysRegIdPtr src_reg = dyn_inst->renamedSrcRegIdx(src_idx); + DPRINTFR(ElasticTrace, "[sn:%lli] Check map for src reg" + " %i (%s)\n", seq_num, + src_reg->regIdx, RegClassStrings[src_reg->regClass]); + auto itr_last_writer = physRegDepMap.find(src_reg->flatIdx); if (itr_last_writer != physRegDepMap.end()) { InstSeqNum last_writer = itr_last_writer->second; // Additionally the dependency distance is kept less than the window @@ -267,10 +268,11 @@ ElasticTrace::updateRegDep(const DynInstPtr &dyn_inst) !dest_reg.isZeroReg()) { // Get the physical register index of the i'th destination // register. - PhysRegIndex phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx); - DPRINTFR(ElasticTrace, "[sn:%lli] Update map for dest reg %i\n", - seq_num, dest_reg.regIdx); - physRegDepMap[phys_dest_reg] = seq_num; + PhysRegIdPtr phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx); + DPRINTFR(ElasticTrace, "[sn:%lli] Update map for dest reg" + " %i (%s)\n", seq_num, dest_reg.regIdx, + RegClassStrings[dest_reg.regClass]); + physRegDepMap[phys_dest_reg->flatIdx] = seq_num; } } maxPhysRegDepMapSize = std::max(physRegDepMap.size(), @@ -281,7 +283,7 @@ void ElasticTrace::removeRegDepMapEntry(const SeqNumRegPair &inst_reg_pair) { DPRINTFR(ElasticTrace, "Remove Map entry for Reg %i\n", - inst_reg_pair.second); + inst_reg_pair.second); auto itr_regdep_map = physRegDepMap.find(inst_reg_pair.second); if (itr_regdep_map != physRegDepMap.end()) physRegDepMap.erase(itr_regdep_map); diff --git a/src/cpu/o3/regfile.cc b/src/cpu/o3/regfile.cc index e1d84c683..ee8d07b3e 100644 --- a/src/cpu/o3/regfile.cc +++ b/src/cpu/o3/regfile.cc @@ -41,18 +41,43 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, : intRegFile(_numPhysicalIntRegs), floatRegFile(_numPhysicalFloatRegs), ccRegFile(_numPhysicalCCRegs), - baseFloatRegIndex(_numPhysicalIntRegs), - baseCCRegIndex(_numPhysicalIntRegs + _numPhysicalFloatRegs), + numPhysicalIntRegs(_numPhysicalIntRegs), + numPhysicalFloatRegs(_numPhysicalFloatRegs), + numPhysicalCCRegs(_numPhysicalCCRegs), totalNumRegs(_numPhysicalIntRegs + _numPhysicalFloatRegs + _numPhysicalCCRegs) { + PhysRegIndex phys_reg; + PhysRegIndex flat_reg_idx = 0; + if (TheISA::NumCCRegs == 0 && _numPhysicalCCRegs != 0) { // Just make this a warning and go ahead and allocate them // anyway, to keep from having to add checks everywhere warn("Non-zero number of physical CC regs specified, even though\n" " ISA does not use them.\n"); } + // The initial batch of registers are the integer ones + for (phys_reg = 0; phys_reg < numPhysicalIntRegs; phys_reg++) { + intRegIds.emplace_back(IntRegClass, phys_reg, flat_reg_idx++); + } + + // The next batch of the registers are the floating-point physical + // registers; put them onto the floating-point free list. + for (phys_reg = 0; phys_reg < numPhysicalFloatRegs; phys_reg++) { + floatRegIds.emplace_back(FloatRegClass, phys_reg, flat_reg_idx++); + } + + // The rest of the registers are the condition-code physical + // registers; put them onto the condition-code free list. + for (phys_reg = 0; phys_reg < numPhysicalCCRegs; phys_reg++) { + ccRegIds.emplace_back(CCRegClass, phys_reg, flat_reg_idx++); + } + + // Misc regs have a fixed mapping but still need PhysRegIds. + for (phys_reg = 0; phys_reg < TheISA::NumMiscRegs; phys_reg++) { + miscRegIds.emplace_back(MiscRegClass, phys_reg, 0); + } } @@ -60,22 +85,25 @@ void PhysRegFile::initFreeList(UnifiedFreeList *freeList) { // Initialize the free lists. - PhysRegIndex reg_idx = 0; + int reg_idx = 0; // The initial batch of registers are the integer ones - while (reg_idx < baseFloatRegIndex) { - freeList->addIntReg(reg_idx++); + for (reg_idx = 0; reg_idx < numPhysicalIntRegs; reg_idx++) { + assert(intRegIds[reg_idx].regIdx == reg_idx); + freeList->addIntReg(&intRegIds[reg_idx]); } // The next batch of the registers are the floating-point physical // registers; put them onto the floating-point free list. - while (reg_idx < baseCCRegIndex) { - freeList->addFloatReg(reg_idx++); + for (reg_idx = 0; reg_idx < numPhysicalFloatRegs; reg_idx++) { + assert(floatRegIds[reg_idx].regIdx == reg_idx); + freeList->addFloatReg(&floatRegIds[reg_idx]); } // The rest of the registers are the condition-code physical // registers; put them onto the condition-code free list. - while (reg_idx < totalNumRegs) { - freeList->addCCReg(reg_idx++); + for (reg_idx = 0; reg_idx < numPhysicalCCRegs; reg_idx++) { + assert(ccRegIds[reg_idx].regIdx == reg_idx); + freeList->addCCReg(&ccRegIds[reg_idx]); } } diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index 8b87725ca..c7935c55c 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -64,34 +64,33 @@ class PhysRegFile /** Integer register file. */ std::vector intRegFile; + std::vector intRegIds; /** Floating point register file. */ std::vector floatRegFile; + std::vector floatRegIds; /** Condition-code register file. */ std::vector ccRegFile; + std::vector ccRegIds; + + /** Misc Reg Ids */ + std::vector miscRegIds; + + /** + * Number of physical general purpose registers + */ + unsigned numPhysicalIntRegs; /** - * The first floating-point physical register index. The physical - * register file has a single continuous index space, with the - * initial indices mapping to the integer registers, followed - * immediately by the floating-point registers. Thus the first - * floating-point index is equal to the number of integer - * registers. - * - * Note that this internal organizational detail on how physical - * register file indices are ordered should *NOT* be exposed - * outside of this class. Other classes can use the is*PhysReg() - * methods to map from a physical register index to a class - * without knowing the internal structure of the index map. + * Number of physical general purpose registers */ - unsigned baseFloatRegIndex; + unsigned numPhysicalFloatRegs; /** - * The first condition-code physical register index. The - * condition-code registers follow the floating-point registers. + * Number of physical general purpose registers */ - unsigned baseCCRegIndex; + unsigned numPhysicalCCRegs; /** Total number of physical registers. */ unsigned totalNumRegs; @@ -114,153 +113,112 @@ class PhysRegFile void initFreeList(UnifiedFreeList *freeList); /** @return the number of integer physical registers. */ - unsigned numIntPhysRegs() const { return baseFloatRegIndex; } + unsigned numIntPhysRegs() const { return numPhysicalIntRegs; } /** @return the number of floating-point physical registers. */ - unsigned numFloatPhysRegs() const - { return baseCCRegIndex - baseFloatRegIndex; } + unsigned numFloatPhysRegs() const { return numPhysicalFloatRegs; } /** @return the number of condition-code physical registers. */ - unsigned numCCPhysRegs() const - { return totalNumRegs - baseCCRegIndex; } + unsigned numCCPhysRegs() const { return numPhysicalCCRegs; } /** @return the total number of physical registers. */ unsigned totalNumPhysRegs() const { return totalNumRegs; } - /** - * @return true if the specified physical register index - * corresponds to an integer physical register. - */ - bool isIntPhysReg(PhysRegIndex reg_idx) const - { - return 0 <= reg_idx && reg_idx < baseFloatRegIndex; - } - - /** - * @return true if the specified physical register index - * corresponds to a floating-point physical register. - */ - bool isFloatPhysReg(PhysRegIndex reg_idx) const - { - return (baseFloatRegIndex <= reg_idx && reg_idx < baseCCRegIndex); - } - - /** - * Return true if the specified physical register index - * corresponds to a condition-code physical register. - */ - bool isCCPhysReg(PhysRegIndex reg_idx) - { - return (baseCCRegIndex <= reg_idx && reg_idx < totalNumRegs); + /** Gets a misc register PhysRegIdPtr. */ + PhysRegIdPtr getMiscRegId(RegIndex reg_idx) { + return &miscRegIds[reg_idx]; } /** Reads an integer register. */ - uint64_t readIntReg(PhysRegIndex reg_idx) const + uint64_t readIntReg(PhysRegIdPtr phys_reg) const { - assert(isIntPhysReg(reg_idx)); + assert(phys_reg->isIntPhysReg()); DPRINTF(IEW, "RegFile: Access to int register %i, has data " - "%#x\n", int(reg_idx), intRegFile[reg_idx]); - return intRegFile[reg_idx]; + "%#x\n", phys_reg->regIdx, intRegFile[phys_reg->regIdx]); + return intRegFile[phys_reg->regIdx]; } /** Reads a floating point register (double precision). */ - FloatReg readFloatReg(PhysRegIndex reg_idx) const + FloatReg readFloatReg(PhysRegIdPtr phys_reg) const { - assert(isFloatPhysReg(reg_idx)); - - // Remove the base Float reg dependency. - PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; + assert(phys_reg->isFloatPhysReg()); DPRINTF(IEW, "RegFile: Access to float register %i, has " - "data %#x\n", int(reg_idx), floatRegFile[reg_offset].q); + "data %#x\n", phys_reg->regIdx, + floatRegFile[phys_reg->regIdx].q); - return floatRegFile[reg_offset].d; + return floatRegFile[phys_reg->regIdx].d; } - FloatRegBits readFloatRegBits(PhysRegIndex reg_idx) const + FloatRegBits readFloatRegBits(PhysRegIdPtr phys_reg) const { - assert(isFloatPhysReg(reg_idx)); + assert(phys_reg->isFloatPhysReg()); - // Remove the base Float reg dependency. - PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; - - FloatRegBits floatRegBits = floatRegFile[reg_offset].q; + FloatRegBits floatRegBits = floatRegFile[phys_reg->regIdx].q; DPRINTF(IEW, "RegFile: Access to float register %i as int, " - "has data %#x\n", int(reg_idx), (uint64_t)floatRegBits); + "has data %#x\n", phys_reg->regIdx, + (uint64_t)floatRegBits); return floatRegBits; } /** Reads a condition-code register. */ - CCReg readCCReg(PhysRegIndex reg_idx) + CCReg readCCReg(PhysRegIdPtr phys_reg) { - assert(isCCPhysReg(reg_idx)); - - // Remove the base CC reg dependency. - PhysRegIndex reg_offset = reg_idx - baseCCRegIndex; + assert(phys_reg->isCCPhysReg()); DPRINTF(IEW, "RegFile: Access to cc register %i, has " - "data %#x\n", int(reg_idx), ccRegFile[reg_offset]); + "data %#x\n", phys_reg->regIdx, + ccRegFile[phys_reg->regIdx]); - return ccRegFile[reg_offset]; + return ccRegFile[phys_reg->regIdx]; } /** Sets an integer register to the given value. */ - void setIntReg(PhysRegIndex reg_idx, uint64_t val) + void setIntReg(PhysRegIdPtr phys_reg, uint64_t val) { - assert(isIntPhysReg(reg_idx)); + assert(phys_reg->isIntPhysReg()); DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n", - int(reg_idx), val); + phys_reg->regIdx, val); - if (reg_idx != TheISA::ZeroReg) - intRegFile[reg_idx] = val; + if (!phys_reg->isZeroReg()) + intRegFile[phys_reg->regIdx] = val; } /** Sets a double precision floating point register to the given value. */ - void setFloatReg(PhysRegIndex reg_idx, FloatReg val) + void setFloatReg(PhysRegIdPtr phys_reg, FloatReg val) { - assert(isFloatPhysReg(reg_idx)); - - // Remove the base Float reg dependency. - PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; + assert(phys_reg->isFloatPhysReg()); DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", - int(reg_idx), (uint64_t)val); + phys_reg->regIdx, (uint64_t)val); -#if THE_ISA == ALPHA_ISA - if (reg_offset != TheISA::ZeroReg) -#endif - floatRegFile[reg_offset].d = val; + if (!phys_reg->isZeroReg()) + floatRegFile[phys_reg->regIdx].d = val; } - void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val) + void setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val) { - assert(isFloatPhysReg(reg_idx)); - - // Remove the base Float reg dependency. - PhysRegIndex reg_offset = reg_idx - baseFloatRegIndex; + assert(phys_reg->isFloatPhysReg()); DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n", - int(reg_idx), (uint64_t)val); + phys_reg->regIdx, (uint64_t)val); - floatRegFile[reg_offset].q = val; + floatRegFile[phys_reg->regIdx].q = val; } /** Sets a condition-code register to the given value. */ - void setCCReg(PhysRegIndex reg_idx, CCReg val) + void setCCReg(PhysRegIdPtr phys_reg, CCReg val) { - assert(isCCPhysReg(reg_idx)); - - // Remove the base CC reg dependency. - PhysRegIndex reg_offset = reg_idx - baseCCRegIndex; + assert(phys_reg->isCCPhysReg()); DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n", - int(reg_idx), (uint64_t)val); + phys_reg->regIdx, (uint64_t)val); - ccRegFile[reg_offset] = val; + ccRegFile[phys_reg->regIdx] = val; } }; diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index c0483d445..ab7ae5f8b 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -119,7 +119,7 @@ class DefaultRename ThreadStatus renameStatus[Impl::MaxThreads]; /** Probe points. */ - typedef typename std::pair SeqNumRegPair; + typedef typename std::pair SeqNumRegPair; /** To probe when register renaming for an instruction is complete */ ProbePointArg *ppRename; /** @@ -299,7 +299,8 @@ class DefaultRename */ struct RenameHistory { RenameHistory(InstSeqNum _instSeqNum, RegId _archReg, - PhysRegIndex _newPhysReg, PhysRegIndex _prevPhysReg) + PhysRegIdPtr _newPhysReg, + PhysRegIdPtr _prevPhysReg) : instSeqNum(_instSeqNum), archReg(_archReg), newPhysReg(_newPhysReg), prevPhysReg(_prevPhysReg) { @@ -310,9 +311,10 @@ class DefaultRename /** The architectural register index that was renamed. */ RegId archReg; /** The new physical register that the arch. register is renamed to. */ - PhysRegIndex newPhysReg; - /** The old physical register that the arch. register was renamed to. */ - PhysRegIndex prevPhysReg; + PhysRegIdPtr newPhysReg; + /** The old physical register that the arch. register was renamed to. + */ + PhysRegIdPtr prevPhysReg; }; /** A per-thread list of all destination register renames, used to either diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index e675efcd5..a92792639 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -983,9 +983,11 @@ DefaultRename::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid) hb_it != historyBuffer[tid].end() && hb_it->instSeqNum <= inst_seq_num) { - DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, " + DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i (%s), " "[sn:%lli].\n", - tid, hb_it->prevPhysReg, hb_it->instSeqNum); + tid, hb_it->prevPhysReg->regIdx, + RegClassStrings[hb_it->prevPhysReg->regClass], + hb_it->instSeqNum); // Don't free special phys regs like misc and zero regs, which // can be recognized because the new mapping is the same as @@ -1013,7 +1015,7 @@ DefaultRename::renameSrcRegs(DynInstPtr &inst, ThreadID tid) for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { RegId src_reg = inst->srcRegIdx(src_idx); RegIndex flat_src_reg; - PhysRegIndex renamed_reg; + PhysRegIdPtr renamed_reg; switch (src_reg.regClass) { case IntRegClass: @@ -1043,21 +1045,27 @@ DefaultRename::renameSrcRegs(DynInstPtr &inst, ThreadID tid) panic("Invalid register class: %d.", src_reg.regClass); } - DPRINTF(Rename, "[tid:%u]: Looking up %s arch reg %i (flattened %i), " - "got phys reg %i\n", tid, RegClassStrings[src_reg.regClass], - (int)src_reg.regIdx, (int)flat_src_reg, (int)renamed_reg); + DPRINTF(Rename, "[tid:%u]: Looking up %s arch reg %i" + " (flattened %i), got phys reg %i (%s)\n", tid, + RegClassStrings[src_reg.regClass], src_reg.regIdx, + flat_src_reg, renamed_reg->regIdx, + RegClassStrings[renamed_reg->regClass]); inst->renameSrcReg(src_idx, renamed_reg); // See if the register is ready or not. if (scoreboard->getReg(renamed_reg)) { - DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n", - tid, renamed_reg); + DPRINTF(Rename, "[tid:%u]: Register %d (flat: %d) (%s)" + " is ready.\n", tid, renamed_reg->regIdx, + renamed_reg->flatIdx, + RegClassStrings[renamed_reg->regClass]); inst->markSrcRegReady(src_idx); } else { - DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n", - tid, renamed_reg); + DPRINTF(Rename, "[tid:%u]: Register %d (flat: %d) (%s)" + " is not ready.\n", tid, renamed_reg->regIdx, + renamed_reg->flatIdx, + RegClassStrings[renamed_reg->regClass]); } ++renameRenameLookups; @@ -1111,9 +1119,11 @@ DefaultRename::renameDestRegs(DynInstPtr &inst, ThreadID tid) // Mark Scoreboard entry as not ready scoreboard->unsetReg(rename_result.first); - DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " - "reg %i.\n", tid, (int)flat_dest_reg, - (int)rename_result.first); + DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i (%s) to physical " + "reg %i (%i).\n", tid, dest_reg.regIdx, + RegClassStrings[dest_reg.regClass], + rename_result.first->regIdx, + rename_result.first->flatIdx); // Record the rename information so that a history can be kept. RenameHistory hb_entry(inst->seqNum, flat_uni_dest_reg, @@ -1426,11 +1436,15 @@ DefaultRename::dumpHistory() buf_it = historyBuffer[tid].begin(); while (buf_it != historyBuffer[tid].end()) { - cprintf("Seq num: %i\nArch reg[%s]: %i New phys reg: %i Old phys " - "reg: %i\n", (*buf_it).instSeqNum, + cprintf("Seq num: %i\nArch reg[%s]: %i New phys reg:" + " %i[%s] Old phys reg: %i[%s]\n", + (*buf_it).instSeqNum, RegClassStrings[(*buf_it).archReg.regClass], (*buf_it).archReg.regIdx, - (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); + (*buf_it).newPhysReg->regIdx, + RegClassStrings[(*buf_it).newPhysReg->regClass], + (*buf_it).prevPhysReg->regIdx, + RegClassStrings[(*buf_it).prevPhysReg->regClass]); buf_it++; } diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc index 6307b58de..4555946c2 100644 --- a/src/cpu/o3/rename_map.cc +++ b/src/cpu/o3/rename_map.cc @@ -60,11 +60,11 @@ SimpleRenameMap::init(unsigned size, SimpleFreeList *_freeList, SimpleRenameMap::RenameInfo SimpleRenameMap::rename(RegIndex arch_reg) { - PhysRegIndex renamed_reg; + PhysRegIdPtr renamed_reg; // Record the current physical register that is renamed to the // requested architected register. - PhysRegIndex prev_reg = map[arch_reg]; + PhysRegIdPtr prev_reg = map[arch_reg]; // If it's not referencing the zero register, then rename the // register. @@ -74,12 +74,14 @@ SimpleRenameMap::rename(RegIndex arch_reg) map[arch_reg] = renamed_reg; } else { // Otherwise return the zero register so nothing bad happens. - assert(prev_reg == zeroReg); - renamed_reg = zeroReg; + assert(prev_reg->isZeroReg()); + renamed_reg = prev_reg; } - DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n", - arch_reg, renamed_reg, prev_reg); + DPRINTF(Rename, "Renamed reg %d to physical reg %d (%d) old mapping was" + " %d (%d)\n", + arch_reg, renamed_reg->regIdx, renamed_reg->flatIdx, + prev_reg->regIdx, prev_reg->flatIdx); return RenameInfo(renamed_reg, prev_reg); } @@ -100,6 +102,7 @@ UnifiedRenameMap::init(PhysRegFile *_regFile, floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg); ccMap.init(TheISA::NumCCRegs, &(freeList->ccList), (RegIndex)-1); + } @@ -126,7 +129,7 @@ UnifiedRenameMap::rename(RegId arch_reg) } -PhysRegIndex +PhysRegIdPtr UnifiedRenameMap::lookup(RegId arch_reg) const { switch (arch_reg.regClass) { @@ -149,7 +152,7 @@ UnifiedRenameMap::lookup(RegId arch_reg) const } void -UnifiedRenameMap::setEntry(RegId arch_reg, PhysRegIndex phys_reg) +UnifiedRenameMap::setEntry(RegId arch_reg, PhysRegIdPtr phys_reg) { switch (arch_reg.regClass) { case IntRegClass: diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh index 2cce29913..f51cf5922 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -42,10 +42,6 @@ * Steve Reinhardt */ -// Todo: Create destructor. -// Have it so that there's a more meaningful name given to the variable -// that marks the beginning of the FP registers. - #ifndef __CPU_O3_RENAME_MAP_HH__ #define __CPU_O3_RENAME_MAP_HH__ @@ -71,7 +67,7 @@ class SimpleRenameMap private: /** The acutal arch-to-phys register map */ - std::vector map; + std::vector map; /** * Pointer to the free list from which new physical registers @@ -107,7 +103,7 @@ class SimpleRenameMap * renamed to, and the previous physical register that the same * logical register was previously mapped to. */ - typedef std::pair RenameInfo; + typedef std::pair RenameInfo; /** * Tell rename map to get a new free physical register to remap @@ -123,7 +119,7 @@ class SimpleRenameMap * @param arch_reg The architectural register to look up. * @return The physical register it is currently mapped to. */ - PhysRegIndex lookup(RegIndex arch_reg) const + PhysRegIdPtr lookup(RegIndex arch_reg) const { assert(arch_reg < map.size()); return map[arch_reg]; @@ -135,7 +131,7 @@ class SimpleRenameMap * @param arch_reg The architectural register to remap. * @param phys_reg The physical register to remap it to. */ - void setEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + void setEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg) { map[arch_reg] = phys_reg; } @@ -162,18 +158,15 @@ class UnifiedRenameMap /** The floating-point register rename map */ SimpleRenameMap floatMap; + /** The condition-code register rename map */ + SimpleRenameMap ccMap; + /** - * The register file object is used only to distinguish integer - * from floating-point physical register indices, which in turn is - * used only for assert statements that make sure the physical - * register indices that get passed in and handed out are of the - * proper class. + * The register file object is used only to get PhysRegIdPtr + * on MiscRegs, as they are stored in it. */ PhysRegFile *regFile; - /** The condition-code register rename map */ - SimpleRenameMap ccMap; - public: typedef SimpleRenameMap::RenameInfo RenameInfo; @@ -207,9 +200,7 @@ class UnifiedRenameMap */ RenameInfo renameInt(RegIndex rel_arch_reg) { - RenameInfo info = intMap.rename(rel_arch_reg); - assert(regFile->isIntPhysReg(info.first)); - return info; + return intMap.rename(rel_arch_reg); } /** @@ -218,9 +209,7 @@ class UnifiedRenameMap */ RenameInfo renameFloat(RegIndex rel_arch_reg) { - RenameInfo info = floatMap.rename(rel_arch_reg); - assert(regFile->isFloatPhysReg(info.first)); - return info; + return floatMap.rename(rel_arch_reg); } /** @@ -229,9 +218,7 @@ class UnifiedRenameMap */ RenameInfo renameCC(RegIndex rel_arch_reg) { - RenameInfo info = ccMap.rename(rel_arch_reg); - assert(regFile->isCCPhysReg(info.first)); - return info; + return ccMap.rename(rel_arch_reg); } /** @@ -241,10 +228,9 @@ class UnifiedRenameMap RenameInfo renameMisc(RegIndex rel_arch_reg) { // misc regs aren't really renamed, just remapped - PhysRegIndex phys_reg = lookupMisc(rel_arch_reg); - // Set the previous register to the same register; mainly it must be - // known that the prev reg was outside the range of normal registers - // so the free list can avoid adding it. + PhysRegIdPtr phys_reg = lookupMisc(rel_arch_reg); + // Set the new register to the previous one to keep the same + // mapping throughout the execution. return RenameInfo(phys_reg, phys_reg); } @@ -256,51 +242,44 @@ class UnifiedRenameMap * @param arch_reg The architectural register to look up. * @return The physical register it is currently mapped to. */ - PhysRegIndex lookup(RegId arch_reg) const; + PhysRegIdPtr lookup(RegId arch_reg) const; /** * Perform lookup() on an integer register, given a * integer register index. */ - PhysRegIndex lookupInt(RegIndex rel_arch_reg) const + PhysRegIdPtr lookupInt(RegIndex rel_arch_reg) const { - PhysRegIndex phys_reg = intMap.lookup(rel_arch_reg); - assert(regFile->isIntPhysReg(phys_reg)); - return phys_reg; + return intMap.lookup(rel_arch_reg); } /** * Perform lookup() on a floating-point register, given a * floating-point register index. */ - PhysRegIndex lookupFloat(RegIndex rel_arch_reg) const + PhysRegIdPtr lookupFloat(RegIndex rel_arch_reg) const { - PhysRegIndex phys_reg = floatMap.lookup(rel_arch_reg); - assert(regFile->isFloatPhysReg(phys_reg)); - return phys_reg; + return floatMap.lookup(rel_arch_reg); } /** * Perform lookup() on a condition-code register, given a * condition-code register index. */ - PhysRegIndex lookupCC(RegIndex rel_arch_reg) const + PhysRegIdPtr lookupCC(RegIndex rel_arch_reg) const { - PhysRegIndex phys_reg = ccMap.lookup(rel_arch_reg); - assert(regFile->isCCPhysReg(phys_reg)); - return phys_reg; + return ccMap.lookup(rel_arch_reg); } /** * Perform lookup() on a misc register, given a relative * misc register index. */ - PhysRegIndex lookupMisc(RegIndex rel_arch_reg) const + PhysRegIdPtr lookupMisc(RegIndex rel_arch_reg) const { - // misc regs aren't really renamed, just given an index - // beyond the range of actual physical registers - PhysRegIndex phys_reg = rel_arch_reg + regFile->totalNumPhysRegs(); - return phys_reg; + // misc regs aren't really renamed, they keep the same + // mapping throughout the execution. + return regFile->getMiscRegId(rel_arch_reg); } /** @@ -311,15 +290,15 @@ class UnifiedRenameMap * @param arch_reg The architectural register to remap. * @param phys_reg The physical register to remap it to. */ - void setEntry(RegId arch_reg, PhysRegIndex phys_reg); + void setEntry(RegId arch_reg, PhysRegIdPtr phys_reg); /** * Perform setEntry() on an integer register, given a * integer register index. */ - void setIntEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + void setIntEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg) { - assert(regFile->isIntPhysReg(phys_reg)); + assert(phys_reg->isIntPhysReg()); intMap.setEntry(arch_reg, phys_reg); } @@ -327,9 +306,9 @@ class UnifiedRenameMap * Perform setEntry() on a floating-point register, given a * floating-point register index. */ - void setFloatEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + void setFloatEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg) { - assert(regFile->isFloatPhysReg(phys_reg)); + assert(phys_reg->isFloatPhysReg()); floatMap.setEntry(arch_reg, phys_reg); } @@ -337,9 +316,9 @@ class UnifiedRenameMap * Perform setEntry() on a condition-code register, given a * condition-code register index. */ - void setCCEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + void setCCEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg) { - assert(regFile->isCCPhysReg(phys_reg)); + assert(phys_reg->isCCPhysReg()); ccMap.setEntry(arch_reg, phys_reg); } diff --git a/src/cpu/o3/scoreboard.cc b/src/cpu/o3/scoreboard.cc index 2b2b091af..e15f9c769 100644 --- a/src/cpu/o3/scoreboard.cc +++ b/src/cpu/o3/scoreboard.cc @@ -36,12 +36,9 @@ #include "debug/Scoreboard.hh" Scoreboard::Scoreboard(const std::string &_my_name, - unsigned _numPhysicalRegs, unsigned _numMiscRegs, - PhysRegIndex _zeroRegIdx, PhysRegIndex _fpZeroRegIdx) + unsigned _numPhysicalRegs) : _name(_my_name), regScoreBoard(_numPhysicalRegs, true), - numPhysRegs(_numPhysicalRegs), - numTotalRegs(_numPhysicalRegs + _numMiscRegs), - zeroRegIdx(_zeroRegIdx), fpZeroRegIdx(_fpZeroRegIdx) + numPhysRegs(_numPhysicalRegs) { } diff --git a/src/cpu/o3/scoreboard.hh b/src/cpu/o3/scoreboard.hh index ec84becdf..44e449944 100644 --- a/src/cpu/o3/scoreboard.hh +++ b/src/cpu/o3/scoreboard.hh @@ -46,12 +46,8 @@ /** * Implements a simple scoreboard to track which registers are * ready. This class operates on the unified physical register space, - * so integer and floating-point registers are not distinguished. For - * convenience, it also accepts operations on the physical-space - * mapping of misc registers, which are numbered starting after the - * end of the actual physical register file. However, there is no - * actual scoreboard for misc registers, and they are always - * considered ready. + * because the different classes of registers do not need to be distinguished. + * Registers being part of a fixed mapping are always considered ready. */ class Scoreboard { @@ -67,38 +63,13 @@ class Scoreboard /** The number of actual physical registers */ unsigned numPhysRegs; - /** - * The total number of registers which can be indexed, including - * the misc registers that come after the physical registers and - * which are hardwired to be always considered ready. - */ - unsigned M5_CLASS_VAR_USED numTotalRegs; - - /** The index of the zero register. */ - PhysRegIndex zeroRegIdx; - - /** The index of the FP zero register. */ - PhysRegIndex fpZeroRegIdx; - - bool isZeroReg(PhysRegIndex idx) const - { - return (idx == zeroRegIdx || - (THE_ISA == ALPHA_ISA && idx == fpZeroRegIdx)); - } - public: /** Constructs a scoreboard. * @param _numPhysicalRegs Number of physical registers. * @param _numMiscRegs Number of miscellaneous registers. - * @param _zeroRegIdx Index of the zero register. - * @param _fpZeroRegIdx Index of the FP zero register (if any, currently - * used only for Alpha). */ Scoreboard(const std::string &_my_name, - unsigned _numPhysicalRegs, - unsigned _numMiscRegs, - PhysRegIndex _zeroRegIdx, - PhysRegIndex _fpZeroRegIdx); + unsigned _numPhysicalRegs); /** Destructor. */ ~Scoreboard() {} @@ -107,54 +78,56 @@ class Scoreboard std::string name() const { return _name; }; /** Checks if the register is ready. */ - bool getReg(PhysRegIndex reg_idx) const + bool getReg(PhysRegIdPtr phys_reg) const { - assert(reg_idx < numTotalRegs); + assert(phys_reg->flatIdx < numPhysRegs); - if (reg_idx >= numPhysRegs) { - // misc regs are always ready + if (phys_reg->isFixedMapping()) { + // Fixed mapping regs are always ready return true; } - bool ready = regScoreBoard[reg_idx]; + bool ready = regScoreBoard[phys_reg->flatIdx]; - if (isZeroReg(reg_idx)) + if (phys_reg->isZeroReg()) assert(ready); return ready; } /** Sets the register as ready. */ - void setReg(PhysRegIndex reg_idx) + void setReg(PhysRegIdPtr phys_reg) { - assert(reg_idx < numTotalRegs); + assert(phys_reg->flatIdx < numPhysRegs); - if (reg_idx >= numPhysRegs) { - // misc regs are always ready, ignore attempts to change that + if (phys_reg->isFixedMapping()) { + // Fixed mapping regs are always ready, ignore attempts to change + // that return; } - DPRINTF(Scoreboard, "Setting reg %i as ready\n", reg_idx); + DPRINTF(Scoreboard, "Setting reg %i (%s) as ready\n", phys_reg->regIdx, + RegClassStrings[phys_reg->regClass]); - assert(reg_idx < numTotalRegs); - regScoreBoard[reg_idx] = true; + regScoreBoard[phys_reg->flatIdx] = true; } /** Sets the register as not ready. */ - void unsetReg(PhysRegIndex reg_idx) + void unsetReg(PhysRegIdPtr phys_reg) { - assert(reg_idx < numTotalRegs); + assert(phys_reg->flatIdx < numPhysRegs); - if (reg_idx >= numPhysRegs) { - // misc regs are always ready, ignore attempts to change that + if (phys_reg->isFixedMapping()) { + // Fixed mapping regs are always ready, ignore attempts to + // change that return; } // zero reg should never be marked unready - if (isZeroReg(reg_idx)) + if (phys_reg->isZeroReg()) return; - regScoreBoard[reg_idx] = false; + regScoreBoard[phys_reg->flatIdx] = false; } };