rename_impl.hh revision 2665
11689SN/A/*
21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31689SN/A * All rights reserved.
41689SN/A *
51689SN/A * Redistribution and use in source and binary forms, with or without
61689SN/A * modification, are permitted provided that the following conditions are
71689SN/A * met: redistributions of source code must retain the above copyright
81689SN/A * notice, this list of conditions and the following disclaimer;
91689SN/A * redistributions in binary form must reproduce the above copyright
101689SN/A * notice, this list of conditions and the following disclaimer in the
111689SN/A * documentation and/or other materials provided with the distribution;
121689SN/A * neither the name of the copyright holders nor the names of its
131689SN/A * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim
291689SN/A */
301689SN/A
311060SN/A#include <list>
321060SN/A
331858SN/A#include "config/full_system.hh"
341717SN/A#include "cpu/o3/rename.hh"
351060SN/A
361061SN/Atemplate <class Impl>
371060SN/ASimpleRename<Impl>::SimpleRename(Params &params)
381060SN/A    : iewToRenameDelay(params.iewToRenameDelay),
391060SN/A      decodeToRenameDelay(params.decodeToRenameDelay),
401060SN/A      commitToRenameDelay(params.commitToRenameDelay),
411060SN/A      renameWidth(params.renameWidth),
421061SN/A      commitWidth(params.commitWidth),
431061SN/A      numInst(0)
441060SN/A{
451060SN/A    _status = Idle;
461060SN/A}
471060SN/A
481061SN/Atemplate <class Impl>
491060SN/Avoid
501062SN/ASimpleRename<Impl>::regStats()
511062SN/A{
521062SN/A    renameSquashCycles
531062SN/A        .name(name() + ".renameSquashCycles")
541062SN/A        .desc("Number of cycles rename is squashing")
551062SN/A        .prereq(renameSquashCycles);
561062SN/A    renameIdleCycles
571062SN/A        .name(name() + ".renameIdleCycles")
581062SN/A        .desc("Number of cycles rename is idle")
591062SN/A        .prereq(renameIdleCycles);
601062SN/A    renameBlockCycles
611062SN/A        .name(name() + ".renameBlockCycles")
621062SN/A        .desc("Number of cycles rename is blocking")
631062SN/A        .prereq(renameBlockCycles);
641062SN/A    renameUnblockCycles
651062SN/A        .name(name() + ".renameUnblockCycles")
661062SN/A        .desc("Number of cycles rename is unblocking")
671062SN/A        .prereq(renameUnblockCycles);
681062SN/A    renameRenamedInsts
691062SN/A        .name(name() + ".renameRenamedInsts")
701062SN/A        .desc("Number of instructions processed by rename")
711062SN/A        .prereq(renameRenamedInsts);
721062SN/A    renameSquashedInsts
731062SN/A        .name(name() + ".renameSquashedInsts")
741062SN/A        .desc("Number of squashed instructions processed by rename")
751062SN/A        .prereq(renameSquashedInsts);
761062SN/A    renameROBFullEvents
771062SN/A        .name(name() + ".renameROBFullEvents")
781062SN/A        .desc("Number of times rename has considered the ROB 'full'")
791062SN/A        .prereq(renameROBFullEvents);
801062SN/A    renameIQFullEvents
811062SN/A        .name(name() + ".renameIQFullEvents")
821062SN/A        .desc("Number of times rename has considered the IQ 'full'")
831062SN/A        .prereq(renameIQFullEvents);
841062SN/A    renameFullRegistersEvents
851062SN/A        .name(name() + ".renameFullRegisterEvents")
861062SN/A        .desc("Number of times there has been no free registers")
871062SN/A        .prereq(renameFullRegistersEvents);
881062SN/A    renameRenamedOperands
891062SN/A        .name(name() + ".renameRenamedOperands")
901062SN/A        .desc("Number of destination operands rename has renamed")
911062SN/A        .prereq(renameRenamedOperands);
921062SN/A    renameRenameLookups
931062SN/A        .name(name() + ".renameRenameLookups")
941062SN/A        .desc("Number of register rename lookups that rename has made")
951062SN/A        .prereq(renameRenameLookups);
961062SN/A    renameHBPlaceHolders
971062SN/A        .name(name() + ".renameHBPlaceHolders")
981062SN/A        .desc("Number of place holders added to the history buffer")
991062SN/A        .prereq(renameHBPlaceHolders);
1001062SN/A    renameCommittedMaps
1011062SN/A        .name(name() + ".renameCommittedMaps")
1021062SN/A        .desc("Number of HB maps that are committed")
1031062SN/A        .prereq(renameCommittedMaps);
1041062SN/A    renameUndoneMaps
1051062SN/A        .name(name() + ".renameUndoneMaps")
1061062SN/A        .desc("Number of HB maps that are undone due to squashing")
1071062SN/A        .prereq(renameUndoneMaps);
1081062SN/A    renameValidUndoneMaps
1091062SN/A        .name(name() + ".renameValidUndoneMaps")
1101062SN/A        .desc("Number of HB maps that are undone, and are not place holders")
1111062SN/A        .prereq(renameValidUndoneMaps);
1121062SN/A}
1131062SN/A
1141062SN/Atemplate <class Impl>
1151062SN/Avoid
1161060SN/ASimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
1171060SN/A{
1181060SN/A    DPRINTF(Rename, "Rename: Setting CPU pointer.\n");
1191060SN/A    cpu = cpu_ptr;
1201060SN/A}
1211060SN/A
1221061SN/Atemplate <class Impl>
1231060SN/Avoid
1241060SN/ASimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1251060SN/A{
1261060SN/A    DPRINTF(Rename, "Rename: Setting time buffer pointer.\n");
1271060SN/A    timeBuffer = tb_ptr;
1281060SN/A
1291060SN/A    // Setup wire to read information from time buffer, from IEW stage.
1301060SN/A    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
1311060SN/A
1321060SN/A    // Setup wire to read infromation from time buffer, from commit stage.
1331060SN/A    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
1341060SN/A
1351060SN/A    // Setup wire to write information to previous stages.
1361060SN/A    toDecode = timeBuffer->getWire(0);
1371060SN/A}
1381060SN/A
1391061SN/Atemplate <class Impl>
1401060SN/Avoid
1411060SN/ASimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
1421060SN/A{
1431060SN/A    DPRINTF(Rename, "Rename: Setting rename queue pointer.\n");
1441060SN/A    renameQueue = rq_ptr;
1451060SN/A
1461060SN/A    // Setup wire to write information to future stages.
1471060SN/A    toIEW = renameQueue->getWire(0);
1481060SN/A}
1491060SN/A
1501061SN/Atemplate <class Impl>
1511060SN/Avoid
1521060SN/ASimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
1531060SN/A{
1541060SN/A    DPRINTF(Rename, "Rename: Setting decode queue pointer.\n");
1551060SN/A    decodeQueue = dq_ptr;
1561060SN/A
1571060SN/A    // Setup wire to get information from decode.
1581060SN/A    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
1591060SN/A}
1601060SN/A
1611061SN/Atemplate <class Impl>
1621060SN/Avoid
1631060SN/ASimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
1641060SN/A{
1651060SN/A    DPRINTF(Rename, "Rename: Setting rename map pointer.\n");
1661060SN/A    renameMap = rm_ptr;
1671060SN/A}
1681060SN/A
1691061SN/Atemplate <class Impl>
1701060SN/Avoid
1711060SN/ASimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
1721060SN/A{
1731060SN/A    DPRINTF(Rename, "Rename: Setting free list pointer.\n");
1741060SN/A    freeList = fl_ptr;
1751060SN/A}
1761060SN/A
1771061SN/Atemplate <class Impl>
1781060SN/Avoid
1791060SN/ASimpleRename<Impl>::dumpHistory()
1801060SN/A{
1811060SN/A    typename list<RenameHistory>::iterator buf_it = historyBuffer.begin();
1821060SN/A
1831060SN/A    while (buf_it != historyBuffer.end())
1841060SN/A    {
1851060SN/A        cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1861060SN/A                "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1871060SN/A                (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1881060SN/A
1891060SN/A        buf_it++;
1901060SN/A    }
1911060SN/A}
1921060SN/A
1931061SN/Atemplate <class Impl>
1941060SN/Avoid
1951060SN/ASimpleRename<Impl>::block()
1961060SN/A{
1971060SN/A    DPRINTF(Rename, "Rename: Blocking.\n");
1981060SN/A    // Set status to Blocked.
1991060SN/A    _status = Blocked;
2001060SN/A
2011060SN/A    // Add the current inputs onto the skid buffer, so they can be
2021060SN/A    // reprocessed when this stage unblocks.
2031060SN/A    skidBuffer.push(*fromDecode);
2041060SN/A
2051060SN/A    // Note that this stage only signals previous stages to stall when
2061060SN/A    // it is the cause of the stall originates at this stage.  Otherwise
2071060SN/A    // the previous stages are expected to check all possible stall signals.
2081060SN/A}
2091060SN/A
2101061SN/Atemplate <class Impl>
2111060SN/Ainline void
2121060SN/ASimpleRename<Impl>::unblock()
2131060SN/A{
2141061SN/A    DPRINTF(Rename, "Rename: Read instructions out of skid buffer this "
2151061SN/A            "cycle.\n");
2161060SN/A    // Remove the now processed instructions from the skid buffer.
2171060SN/A    skidBuffer.pop();
2181060SN/A
2191060SN/A    // If there's still information in the skid buffer, then
2201060SN/A    // continue to tell previous stages to stall.  They will be
2211060SN/A    // able to restart once the skid buffer is empty.
2221060SN/A    if (!skidBuffer.empty()) {
2231062SN/A        toDecode->renameInfo.stall = true;
2241060SN/A    } else {
2251060SN/A        DPRINTF(Rename, "Rename: Done unblocking.\n");
2261060SN/A        _status = Running;
2271060SN/A    }
2281060SN/A}
2291060SN/A
2301061SN/Atemplate <class Impl>
2311060SN/Avoid
2321060SN/ASimpleRename<Impl>::doSquash()
2331060SN/A{
2341060SN/A    typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
2351060SN/A
2361060SN/A    InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
2371060SN/A
2381858SN/A#if FULL_SYSTEM
2391060SN/A    assert(!historyBuffer.empty());
2401060SN/A#else
2411060SN/A    // After a syscall squashes everything, the history buffer may be empty
2421060SN/A    // but the ROB may still be squashing instructions.
2431060SN/A    if (historyBuffer.empty()) {
2441060SN/A        return;
2451060SN/A    }
2461060SN/A#endif // FULL_SYSTEM
2471060SN/A
2481060SN/A    // Go through the most recent instructions, undoing the mappings
2491060SN/A    // they did and freeing up the registers.
2501060SN/A    while ((*hb_it).instSeqNum > squashed_seq_num)
2511060SN/A    {
2521062SN/A        assert(hb_it != historyBuffer.end());
2531062SN/A
2541060SN/A        DPRINTF(Rename, "Rename: Removing history entry with sequence "
2551060SN/A                "number %i.\n", (*hb_it).instSeqNum);
2561060SN/A
2571060SN/A        // If it's not simply a place holder, then add the registers.
2581060SN/A        if (!(*hb_it).placeHolder) {
2591060SN/A            // Tell the rename map to set the architected register to the
2601060SN/A            // previous physical register that it was renamed to.
2611060SN/A            renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg);
2621060SN/A
2631060SN/A            // Put the renamed physical register back on the free list.
2641060SN/A            freeList->addReg(hb_it->newPhysReg);
2651062SN/A
2661062SN/A            ++renameValidUndoneMaps;
2671060SN/A        }
2681060SN/A
2691061SN/A        historyBuffer.erase(hb_it++);
2701061SN/A
2711062SN/A        ++renameUndoneMaps;
2721060SN/A    }
2731060SN/A}
2741060SN/A
2751061SN/Atemplate <class Impl>
2761060SN/Avoid
2771060SN/ASimpleRename<Impl>::squash()
2781060SN/A{
2791060SN/A    DPRINTF(Rename, "Rename: Squashing instructions.\n");
2801060SN/A    // Set the status to Squashing.
2811060SN/A    _status = Squashing;
2821060SN/A
2831061SN/A    numInst = 0;
2841061SN/A
2851060SN/A    // Clear the skid buffer in case it has any data in it.
2861060SN/A    while (!skidBuffer.empty())
2871060SN/A    {
2881060SN/A        skidBuffer.pop();
2891060SN/A    }
2901060SN/A
2911060SN/A    doSquash();
2921060SN/A}
2931060SN/A
2941060SN/Atemplate<class Impl>
2951060SN/Avoid
2961060SN/ASimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
2971060SN/A{
2981060SN/A    DPRINTF(Rename, "Rename: Removing a committed instruction from the "
2991061SN/A            "history buffer, until sequence number %lli.\n", inst_seq_num);
3001060SN/A    typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
3011060SN/A
3021061SN/A    --hb_it;
3031060SN/A
3041060SN/A    if (hb_it->instSeqNum > inst_seq_num) {
3051060SN/A        DPRINTF(Rename, "Rename: Old sequence number encountered.  Ensure "
3061060SN/A                "that a syscall happened recently.\n");
3071060SN/A        return;
3081060SN/A    }
3091060SN/A
3101061SN/A    while ((*hb_it).instSeqNum != inst_seq_num)
3111060SN/A    {
3121060SN/A        // Make sure we haven't gone off the end of the list.
3131060SN/A        assert(hb_it != historyBuffer.end());
3141060SN/A
3151060SN/A        // In theory instructions at the end of the history buffer
3161060SN/A        // should be older than the instruction being removed, which
3171060SN/A        // means they will have a lower sequence number.  Also the
3181060SN/A        // instruction being removed from the history really should
3191060SN/A        // be the last instruction in the list, as it is the instruction
3201060SN/A        // that was just committed that is being removed.
3211060SN/A        assert(hb_it->instSeqNum < inst_seq_num);
3221061SN/A        DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence"
3231061SN/A                " number %i.\n",
3241061SN/A                (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
3251061SN/A
3261061SN/A        if (!(*hb_it).placeHolder) {
3271061SN/A            freeList->addReg((*hb_it).prevPhysReg);
3281062SN/A            ++renameCommittedMaps;
3291061SN/A        }
3301061SN/A
3311061SN/A        historyBuffer.erase(hb_it--);
3321060SN/A    }
3331060SN/A
3341062SN/A    // Finally free up the previous register of the finished instruction
3351061SN/A    // itself.
3361060SN/A    if (!(*hb_it).placeHolder) {
3371060SN/A        freeList->addReg(hb_it->prevPhysReg);
3381062SN/A        ++renameCommittedMaps;
3391060SN/A    }
3401060SN/A
3411060SN/A    historyBuffer.erase(hb_it);
3421060SN/A}
3431060SN/A
3441061SN/Atemplate <class Impl>
3451061SN/Ainline void
3461061SN/ASimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst)
3471061SN/A{
3481061SN/A    unsigned num_src_regs = inst->numSrcRegs();
3491061SN/A
3501061SN/A    // Get the architectual register numbers from the source and
3511061SN/A    // destination operands, and redirect them to the right register.
3521061SN/A    // Will need to mark dependencies though.
3531061SN/A    for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
3541061SN/A    {
3551061SN/A        RegIndex src_reg = inst->srcRegIdx(src_idx);
3561061SN/A
3571061SN/A        // Look up the source registers to get the phys. register they've
3581061SN/A        // been renamed to, and set the sources to those registers.
3591062SN/A        PhysRegIndex renamed_reg = renameMap->lookup(src_reg);
3601061SN/A
3611061SN/A        DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
3621061SN/A                "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
3631061SN/A
3641061SN/A        inst->renameSrcReg(src_idx, renamed_reg);
3651061SN/A
3661061SN/A        // Either incorporate it into the info passed back,
3671061SN/A        // or make another function call to see if that register is
3681061SN/A        // ready or not.
3691061SN/A        if (renameMap->isReady(renamed_reg)) {
3701061SN/A            DPRINTF(Rename, "Rename: Register is ready.\n");
3711061SN/A
3721061SN/A            inst->markSrcRegReady(src_idx);
3731061SN/A        }
3741062SN/A
3751062SN/A        ++renameRenameLookups;
3761061SN/A    }
3771061SN/A}
3781061SN/A
3791061SN/Atemplate <class Impl>
3801061SN/Ainline void
3811061SN/ASimpleRename<Impl>::renameDestRegs(DynInstPtr &inst)
3821061SN/A{
3831061SN/A    typename SimpleRenameMap::RenameInfo rename_result;
3841061SN/A
3851061SN/A    unsigned num_dest_regs = inst->numDestRegs();
3861061SN/A
3871061SN/A    // If it's an instruction with no destination registers, then put
3881061SN/A    // a placeholder within the history buffer.  It might be better
3891061SN/A    // to not put it in the history buffer at all (other than branches,
3901061SN/A    // which always need at least a place holder), and differentiate
3911061SN/A    // between instructions with and without destination registers
3921061SN/A    // when getting from commit the instructions that committed.
3931061SN/A    if (num_dest_regs == 0) {
3941061SN/A        RenameHistory hb_entry(inst->seqNum);
3951061SN/A
3961061SN/A        historyBuffer.push_front(hb_entry);
3971061SN/A
3981061SN/A        DPRINTF(Rename, "Rename: Adding placeholder instruction to "
3991061SN/A                "history buffer, sequence number %lli.\n",
4001061SN/A                inst->seqNum);
4011062SN/A
4021062SN/A        ++renameHBPlaceHolders;
4031062SN/A    } else {
4041062SN/A
4051062SN/A        // Rename the destination registers.
4061062SN/A        for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
4071062SN/A        {
4081062SN/A            RegIndex dest_reg = inst->destRegIdx(dest_idx);
4091062SN/A
4101062SN/A            // Get the physical register that the destination will be
4111062SN/A            // renamed to.
4121062SN/A            rename_result = renameMap->rename(dest_reg);
4131062SN/A
4141062SN/A            DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
4151062SN/A                    "reg %i.\n", (int)dest_reg,
4161062SN/A                    (int)rename_result.first);
4171062SN/A
4181062SN/A            // Record the rename information so that a history can be kept.
4191062SN/A            RenameHistory hb_entry(inst->seqNum, dest_reg,
4201062SN/A                                   rename_result.first,
4211062SN/A                                   rename_result.second);
4221062SN/A
4231062SN/A            historyBuffer.push_front(hb_entry);
4241062SN/A
4251062SN/A            DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
4261062SN/A                    "sequence number %lli.\n",
4271062SN/A                    (*historyBuffer.begin()).instSeqNum);
4281062SN/A
4291062SN/A            // Tell the instruction to rename the appropriate destination
4301062SN/A            // register (dest_idx) to the new physical register
4311062SN/A            // (rename_result.first), and record the previous physical
4321062SN/A            // register that the same logical register was renamed to
4331062SN/A            // (rename_result.second).
4341062SN/A            inst->renameDestReg(dest_idx,
4351062SN/A                                rename_result.first,
4361062SN/A                                rename_result.second);
4371062SN/A
4381062SN/A            ++renameRenamedOperands;
4391062SN/A        }
4401061SN/A    }
4411061SN/A}
4421061SN/A
4431061SN/Atemplate <class Impl>
4441061SN/Ainline int
4451061SN/ASimpleRename<Impl>::calcFreeROBEntries()
4461061SN/A{
4471061SN/A    return fromCommit->commitInfo.freeROBEntries -
4481061SN/A        renameWidth * iewToRenameDelay;
4491061SN/A}
4501061SN/A
4511061SN/Atemplate <class Impl>
4521061SN/Ainline int
4531061SN/ASimpleRename<Impl>::calcFreeIQEntries()
4541061SN/A{
4551061SN/A    return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;
4561061SN/A}
4571061SN/A
4581060SN/Atemplate<class Impl>
4591060SN/Avoid
4601060SN/ASimpleRename<Impl>::tick()
4611060SN/A{
4621060SN/A    // Rename will need to try to rename as many instructions as it
4631060SN/A    // has bandwidth, unless it is blocked.
4641060SN/A
4651060SN/A    // Check if _status is BarrierStall.  If so, then check if the number
4661060SN/A    // of free ROB entries is equal to the number of total ROB entries.
4671060SN/A    // Once equal then wake this stage up.  Set status to unblocking maybe.
4681060SN/A
4691060SN/A    if (_status != Blocked && _status != Squashing) {
4701060SN/A        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "
4711060SN/A                        "run stage.\n");
4721060SN/A        // Make sure that the skid buffer has something in it if the
4731060SN/A        // status is unblocking.
4741060SN/A        assert(_status == Unblocking ? !skidBuffer.empty() : 1);
4751060SN/A
4761060SN/A        rename();
4771060SN/A
4781060SN/A        // If the status was unblocking, then instructions from the skid
4791060SN/A        // buffer were used.  Remove those instructions and handle
4801060SN/A        // the rest of unblocking.
4811060SN/A        if (_status == Unblocking) {
4821062SN/A            ++renameUnblockCycles;
4831062SN/A
4841061SN/A            if (fromDecode->size > 0) {
4851061SN/A                // Add the current inputs onto the skid buffer, so they can be
4861061SN/A                // reprocessed when this stage unblocks.
4871061SN/A                skidBuffer.push(*fromDecode);
4881061SN/A            }
4891061SN/A
4901060SN/A            unblock();
4911060SN/A        }
4921060SN/A    } else if (_status == Blocked) {
4931062SN/A        ++renameBlockCycles;
4941062SN/A
4951060SN/A        // If stage is blocked and still receiving valid instructions,
4961060SN/A        // make sure to store them in the skid buffer.
4971061SN/A        if (fromDecode->size > 0) {
4981060SN/A
4991060SN/A            block();
5001060SN/A
5011060SN/A            // Continue to tell previous stage to stall.
5021060SN/A            toDecode->renameInfo.stall = true;
5031060SN/A        }
5041060SN/A
5051060SN/A        if (!fromIEW->iewInfo.stall &&
5061060SN/A            !fromCommit->commitInfo.stall &&
5071061SN/A            calcFreeROBEntries() > 0 &&
5081061SN/A            calcFreeIQEntries() > 0 &&
5091061SN/A            renameMap->numFreeEntries() > 0) {
5101060SN/A
5111060SN/A            // Need to be sure to check all blocking conditions above.
5121060SN/A            // If they have cleared, then start unblocking.
5131060SN/A            DPRINTF(Rename, "Rename: Stall signals cleared, going to "
5141060SN/A                    "unblock.\n");
5151060SN/A            _status = Unblocking;
5161060SN/A
5171060SN/A            // Continue to tell previous stage to block until this stage
5181060SN/A            // is done unblocking.
5191060SN/A            toDecode->renameInfo.stall = true;
5201060SN/A        } else {
5211060SN/A            // Otherwise no conditions have changed.  Tell previous
5221060SN/A            // stage to continue blocking.
5231060SN/A            toDecode->renameInfo.stall = true;
5241060SN/A        }
5251060SN/A
5261060SN/A        if (fromCommit->commitInfo.squash ||
5271060SN/A            fromCommit->commitInfo.robSquashing) {
5281060SN/A            squash();
5291060SN/A            return;
5301060SN/A        }
5311060SN/A    } else if (_status == Squashing) {
5321062SN/A        ++renameSquashCycles;
5331062SN/A
5341060SN/A        if (fromCommit->commitInfo.squash) {
5351060SN/A            squash();
5361060SN/A        } else if (!fromCommit->commitInfo.squash &&
5371060SN/A                   !fromCommit->commitInfo.robSquashing) {
5381060SN/A
5391060SN/A            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");
5401060SN/A            _status = Running;
5411684SN/A            rename();
5421060SN/A        } else {
5431060SN/A            doSquash();
5441060SN/A        }
5451060SN/A    }
5461060SN/A
5471060SN/A    // Ugly code, revamp all of the tick() functions eventually.
5481060SN/A    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {
5491858SN/A#if !FULL_SYSTEM
5501062SN/A        if (!fromCommit->commitInfo.squash) {
5511062SN/A            removeFromHistory(fromCommit->commitInfo.doneSeqNum);
5521062SN/A        }
5531062SN/A#else
5541060SN/A        removeFromHistory(fromCommit->commitInfo.doneSeqNum);
5551062SN/A#endif
5561060SN/A    }
5571060SN/A
5581060SN/A}
5591060SN/A
5601060SN/Atemplate<class Impl>
5611060SN/Avoid
5621060SN/ASimpleRename<Impl>::rename()
5631060SN/A{
5641060SN/A    // Check if any of the stages ahead of rename are telling rename
5651060SN/A    // to squash.  The squash() function will also take care of fixing up
5661060SN/A    // the rename map and the free list.
5671060SN/A    if (fromCommit->commitInfo.squash ||
5681060SN/A        fromCommit->commitInfo.robSquashing) {
5691061SN/A        DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");
5701060SN/A        squash();
5711060SN/A        return;
5721060SN/A    }
5731060SN/A
5741060SN/A    // Check if time buffer is telling this stage to stall.
5751060SN/A    if (fromIEW->iewInfo.stall ||
5761060SN/A        fromCommit->commitInfo.stall) {
5771060SN/A        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "
5781060SN/A                        "stall.\n");
5791060SN/A        block();
5801060SN/A        return;
5811060SN/A    }
5821060SN/A
5831060SN/A    // Check if the current status is squashing.  If so, set its status
5841060SN/A    // to running and resume execution the next cycle.
5851060SN/A    if (_status == Squashing) {
5861060SN/A        DPRINTF(Rename, "Rename: Done squashing.\n");
5871060SN/A        _status = Running;
5881060SN/A        return;
5891060SN/A    }
5901060SN/A
5911060SN/A    // Check the decode queue to see if instructions are available.
5921060SN/A    // If there are no available instructions to rename, then do nothing.
5931060SN/A    // Or, if the stage is currently unblocking, then go ahead and run it.
5941061SN/A    if (fromDecode->size == 0 && _status != Unblocking) {
5951060SN/A        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
5961060SN/A        // Should I change status to idle?
5971060SN/A        return;
5981060SN/A    }
5991060SN/A
6001061SN/A    ////////////////////////////////////
6011061SN/A    // Actual rename part.
6021061SN/A    ////////////////////////////////////
6031060SN/A
6041061SN/A    DynInstPtr inst;
6051060SN/A
6061061SN/A    // If we're unblocking, then we may be in the middle of an instruction
6071061SN/A    // group.  Subtract off numInst to get the proper number of instructions
6081061SN/A    // left.
6091061SN/A    int insts_available = _status == Unblocking ?
6101061SN/A        skidBuffer.front().size - numInst :
6111061SN/A        fromDecode->size;
6121060SN/A
6131061SN/A    bool block_this_cycle = false;
6141060SN/A
6151060SN/A    // Will have to do a different calculation for the number of free
6161060SN/A    // entries.  Number of free entries recorded on this cycle -
6171060SN/A    // renameWidth * renameToDecodeDelay
6181061SN/A    int free_rob_entries = calcFreeROBEntries();
6191061SN/A    int free_iq_entries = calcFreeIQEntries();
6201061SN/A    int min_iq_rob = min(free_rob_entries, free_iq_entries);
6211061SN/A
6221061SN/A    unsigned to_iew_index = 0;
6231060SN/A
6241060SN/A    // Check if there's any space left.
6251061SN/A    if (min_iq_rob <= 0) {
6261060SN/A        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
6271060SN/A                "entries.\n"
6281060SN/A                "Rename: ROB has %d free entries.\n"
6291060SN/A                "Rename: IQ has %d free entries.\n",
6301060SN/A                free_rob_entries,
6311060SN/A                free_iq_entries);
6321060SN/A        block();
6331060SN/A        // Tell previous stage to stall.
6341060SN/A        toDecode->renameInfo.stall = true;
6351060SN/A
6361062SN/A        if (free_rob_entries <= 0) {
6371062SN/A            ++renameROBFullEvents;
6381062SN/A        } else {
6391062SN/A            ++renameIQFullEvents;
6401062SN/A        }
6411062SN/A
6421060SN/A        return;
6431061SN/A    } else if (min_iq_rob < insts_available) {
6441061SN/A        DPRINTF(Rename, "Rename: Will have to block this cycle.  Only "
6451061SN/A                "%i insts can be renamed due to IQ/ROB limits.\n",
6461061SN/A                min_iq_rob);
6471061SN/A
6481061SN/A        insts_available = min_iq_rob;
6491061SN/A
6501061SN/A        block_this_cycle = true;
6511062SN/A
6521062SN/A        if (free_rob_entries < free_iq_entries) {
6531062SN/A            ++renameROBFullEvents;
6541062SN/A        } else {
6551062SN/A            ++renameIQFullEvents;
6561062SN/A        }
6571060SN/A    }
6581060SN/A
6591061SN/A    while (insts_available > 0) {
6601060SN/A        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
6611060SN/A
6621060SN/A        // Get the next instruction either from the skid buffer or the
6631060SN/A        // decode queue.
6641061SN/A        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
6651061SN/A               fromDecode->insts[numInst];
6661061SN/A
6671061SN/A        if (inst->isSquashed()) {
6681061SN/A            DPRINTF(Rename, "Rename: instruction %i with PC %#x is "
6691061SN/A                    "squashed, skipping.\n",
6701061SN/A                    inst->seqNum, inst->readPC());
6711061SN/A
6721061SN/A            // Go to the next instruction.
6731061SN/A            ++numInst;
6741061SN/A
6751062SN/A            ++renameSquashedInsts;
6761062SN/A
6771061SN/A            // Decrement how many instructions are available.
6781061SN/A            --insts_available;
6791061SN/A
6801061SN/A            continue;
6811061SN/A        }
6821060SN/A
6831060SN/A        DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
6841061SN/A                inst->seqNum, inst->readPC());
6851060SN/A
6861060SN/A        // If it's a trap instruction, then it needs to wait here within
6871060SN/A        // rename until the ROB is empty.  Needs a way to detect that the
6881060SN/A        // ROB is empty.  Maybe an event?
6891060SN/A        // Would be nice if it could be avoided putting this into a
6901060SN/A        // specific stage and instead just put it into the AlphaFullCPU.
6911060SN/A        // Might not really be feasible though...
6921060SN/A        // (EXCB, TRAPB)
6931060SN/A        if (inst->isSerializing()) {
6941060SN/A            panic("Rename: Serializing instruction encountered.\n");
6951060SN/A            DPRINTF(Rename, "Rename: Serializing instruction "
6961060SN/A                            "encountered.\n");
6971060SN/A
6981060SN/A            // Change status over to BarrierStall so that other stages know
6991060SN/A            // what this is blocked on.
7001060SN/A            _status = BarrierStall;
7011060SN/A
7021061SN/A            block_this_cycle = true;
7031060SN/A
7041060SN/A            break;
7051060SN/A        }
7061060SN/A
7071061SN/A        // Check here to make sure there are enough destination registers
7081061SN/A        // to rename to.  Otherwise block.
7091061SN/A        if (renameMap->numFreeEntries() < inst->numDestRegs())
7101061SN/A        {
7111061SN/A            DPRINTF(Rename, "Rename: Blocking due to lack of free "
7121061SN/A                            "physical registers to rename to.\n");
7131061SN/A            // Need some sort of event based on a register being freed.
7141060SN/A
7151061SN/A            block_this_cycle = true;
7161060SN/A
7171062SN/A            ++renameFullRegistersEvents;
7181062SN/A
7191060SN/A            break;
7201060SN/A        }
7211060SN/A
7221061SN/A        renameSrcRegs(inst);
7231060SN/A
7241061SN/A        renameDestRegs(inst);
7251060SN/A
7261060SN/A        // Put instruction in rename queue.
7271061SN/A        toIEW->insts[to_iew_index] = inst;
7281061SN/A        ++(toIEW->size);
7291060SN/A
7301060SN/A        // Decrease the number of free ROB and IQ entries.
7311060SN/A        --free_rob_entries;
7321060SN/A        --free_iq_entries;
7331060SN/A
7341060SN/A        // Increment which instruction we're on.
7351061SN/A        ++to_iew_index;
7361061SN/A        ++numInst;
7371060SN/A
7381062SN/A        ++renameRenamedInsts;
7391062SN/A
7401061SN/A        // Decrement how many instructions are available.
7411061SN/A        --insts_available;
7421060SN/A    }
7431060SN/A
7441061SN/A    // Check if there's any instructions left that haven't yet been renamed.
7451061SN/A    // If so then block.
7461061SN/A    if (block_this_cycle) {
7471061SN/A        block();
7481061SN/A
7491061SN/A        toDecode->renameInfo.stall = true;
7501061SN/A    } else {
7511061SN/A        // If we had a successful rename and didn't have to exit early, then
7521061SN/A        // reset numInst so it will refer to the correct instruction on next
7531061SN/A        // run.
7541061SN/A        numInst = 0;
7551061SN/A    }
7561060SN/A}
757