rename_impl.hh revision 1061
11689SN/A#include <list>
29444SAndreas.Sandberg@ARM.com
39913Ssteve.reinhardt@amd.com#include "cpu/beta_cpu/rename.hh"
47854SAli.Saidi@ARM.com
57854SAli.Saidi@ARM.comtemplate <class Impl>
67854SAli.Saidi@ARM.comSimpleRename<Impl>::SimpleRename(Params &params)
77854SAli.Saidi@ARM.com    : iewToRenameDelay(params.iewToRenameDelay),
87854SAli.Saidi@ARM.com      decodeToRenameDelay(params.decodeToRenameDelay),
97854SAli.Saidi@ARM.com      commitToRenameDelay(params.commitToRenameDelay),
107854SAli.Saidi@ARM.com      renameWidth(params.renameWidth),
117854SAli.Saidi@ARM.com      commitWidth(params.commitWidth),
127854SAli.Saidi@ARM.com      numInst(0)
137854SAli.Saidi@ARM.com{
147854SAli.Saidi@ARM.com    _status = Idle;
152329SN/A}
161689SN/A
171689SN/Atemplate <class Impl>
181689SN/Avoid
191689SN/ASimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
201689SN/A{
211689SN/A    DPRINTF(Rename, "Rename: Setting CPU pointer.\n");
221689SN/A    cpu = cpu_ptr;
231689SN/A}
241689SN/A
251689SN/Atemplate <class Impl>
261689SN/Avoid
271689SN/ASimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
281689SN/A{
291689SN/A    DPRINTF(Rename, "Rename: Setting time buffer pointer.\n");
301689SN/A    timeBuffer = tb_ptr;
311689SN/A
321689SN/A    // Setup wire to read information from time buffer, from IEW stage.
331689SN/A    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
341689SN/A
351689SN/A    // Setup wire to read infromation from time buffer, from commit stage.
361689SN/A    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
371689SN/A
381689SN/A    // Setup wire to write information to previous stages.
391689SN/A    toDecode = timeBuffer->getWire(0);
402665Ssaidi@eecs.umich.edu}
412665Ssaidi@eecs.umich.edu
422935Sksewell@umich.edutemplate <class Impl>
431689SN/Avoid
441689SN/ASimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
451060SN/A{
461060SN/A    DPRINTF(Rename, "Rename: Setting rename queue pointer.\n");
473773Sgblack@eecs.umich.edu    renameQueue = rq_ptr;
486329Sgblack@eecs.umich.edu
496658Snate@binkert.org    // Setup wire to write information to future stages.
501717SN/A    toIEW = renameQueue->getWire(0);
519913Ssteve.reinhardt@amd.com}
528232Snate@binkert.org
538232Snate@binkert.orgtemplate <class Impl>
549527SMatt.Horsnell@arm.comvoid
555529Snate@binkert.orgSimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
561060SN/A{
576221Snate@binkert.org    DPRINTF(Rename, "Rename: Setting decode queue pointer.\n");
586221Snate@binkert.org    decodeQueue = dq_ptr;
591061SN/A
605529Snate@binkert.org    // Setup wire to get information from decode.
614329Sktlim@umich.edu    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
624329Sktlim@umich.edu
632292SN/A}
642292SN/A
652292SN/Atemplate <class Impl>
662292SN/Avoid
675529Snate@binkert.orgSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
682361SN/A{
691060SN/A    DPRINTF(Rename, "Rename: Setting rename map pointer.\n");
702292SN/A    renameMap = rm_ptr;
718907Slukefahr@umich.edu}
722292SN/A
732292SN/Atemplate <class Impl>
742292SN/Avoid
752292SN/ASimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
762292SN/A{
772292SN/A    DPRINTF(Rename, "Rename: Setting free list pointer.\n");
782292SN/A    freeList = fl_ptr;
791060SN/A}
801060SN/A
811061SN/Atemplate <class Impl>
821060SN/Avoid
832292SN/ASimpleRename<Impl>::dumpHistory()
841062SN/A{
851062SN/A    typename list<RenameHistory>::iterator buf_it = historyBuffer.begin();
868240Snate@binkert.org
871062SN/A    while (buf_it != historyBuffer.end())
881062SN/A    {
891062SN/A        cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
908240Snate@binkert.org                "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
911062SN/A                (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
921062SN/A
931062SN/A        buf_it++;
948240Snate@binkert.org    }
951062SN/A}
961062SN/A
972301SN/Atemplate <class Impl>
988240Snate@binkert.orgvoid
992301SN/ASimpleRename<Impl>::block()
1002301SN/A{
1012292SN/A    DPRINTF(Rename, "Rename: Blocking.\n");
1028240Snate@binkert.org    // Set status to Blocked.
1032292SN/A    _status = Blocked;
1042292SN/A
1051062SN/A    // Add the current inputs onto the skid buffer, so they can be
1068240Snate@binkert.org    // reprocessed when this stage unblocks.
1071062SN/A    skidBuffer.push(*fromDecode);
1081062SN/A
1091062SN/A    // Note that this stage only signals previous stages to stall when
1108240Snate@binkert.org    // it is the cause of the stall originates at this stage.  Otherwise
1111062SN/A    // the previous stages are expected to check all possible stall signals.
1121062SN/A}
1131062SN/A
1148240Snate@binkert.orgtemplate <class Impl>
1151062SN/Ainline void
1161062SN/ASimpleRename<Impl>::unblock()
1171062SN/A{
1188240Snate@binkert.org    DPRINTF(Rename, "Rename: Read instructions out of skid buffer this "
1192292SN/A            "cycle.\n");
1201062SN/A    // Remove the now processed instructions from the skid buffer.
1211062SN/A    skidBuffer.pop();
1228240Snate@binkert.org
1232292SN/A    // If there's still information in the skid buffer, then
1241062SN/A    // continue to tell previous stages to stall.  They will be
1252292SN/A    // able to restart once the skid buffer is empty.
1268240Snate@binkert.org    if (!skidBuffer.empty()) {
1272292SN/A                toDecode->renameInfo.stall = true;
1282292SN/A    } else {
1291062SN/A        DPRINTF(Rename, "Rename: Done unblocking.\n");
1308240Snate@binkert.org        _status = Running;
1311062SN/A    }
1321062SN/A}
1331062SN/A
1348240Snate@binkert.orgtemplate <class Impl>
1351062SN/Avoid
1361062SN/ASimpleRename<Impl>::doSquash()
1371062SN/A{
1388240Snate@binkert.org    typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
1391062SN/A//    typename list<RenameHistory>::iterator delete_it;
1401062SN/A
1411062SN/A    InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
1428240Snate@binkert.org
1431062SN/A#ifdef FULL_SYSTEM
1441062SN/A    assert(!historyBuffer.empty());
1451062SN/A#else
1468240Snate@binkert.org    // After a syscall squashes everything, the history buffer may be empty
1471062SN/A    // but the ROB may still be squashing instructions.
1481062SN/A    if (historyBuffer.empty()) {
1492301SN/A        return;
1508240Snate@binkert.org    }
1512301SN/A#endif // FULL_SYSTEM
1522301SN/A
1532301SN/A    // Go through the most recent instructions, undoing the mappings
1542301SN/A    // they did and freeing up the registers.
1558240Snate@binkert.org    while ((*hb_it).instSeqNum > squashed_seq_num)
1562301SN/A    {
1572301SN/A        DPRINTF(Rename, "Rename: Removing history entry with sequence "
1582301SN/A                "number %i.\n", (*hb_it).instSeqNum);
1592307SN/A
1608240Snate@binkert.org        // If it's not simply a place holder, then add the registers.
1612307SN/A        if (!(*hb_it).placeHolder) {
1622307SN/A            // Tell the rename map to set the architected register to the
1632307SN/A            // previous physical register that it was renamed to.
1647897Shestness@cs.utexas.edu            renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg);
1658240Snate@binkert.org
1667897Shestness@cs.utexas.edu            // Put the renamed physical register back on the free list.
1677897Shestness@cs.utexas.edu            freeList->addReg(hb_it->newPhysReg);
1687897Shestness@cs.utexas.edu        }
1698240Snate@binkert.org
1707897Shestness@cs.utexas.edu//        delete_it = hb_it;
1717897Shestness@cs.utexas.edu
1721062SN/A//        hb_it++;
1731062SN/A
1741062SN/A        historyBuffer.erase(hb_it++);
1751062SN/A
1762292SN/A        assert(hb_it != historyBuffer.end());
1771060SN/A    }
1781060SN/A}
1791060SN/A
1801060SN/Atemplate <class Impl>
1811060SN/Avoid
1821060SN/ASimpleRename<Impl>::squash()
1831060SN/A{
1841060SN/A    DPRINTF(Rename, "Rename: Squashing instructions.\n");
1851060SN/A    // Set the status to Squashing.
1861060SN/A    _status = Squashing;
1871060SN/A
1881060SN/A    numInst = 0;
1891060SN/A
1901061SN/A    // Clear the skid buffer in case it has any data in it.
1911060SN/A    while (!skidBuffer.empty())
1922292SN/A    {
1931060SN/A        skidBuffer.pop();
1941060SN/A    }
1951060SN/A
1961060SN/A    doSquash();
1971060SN/A}
1981060SN/A
1991060SN/A// In the future, when a SmartPtr is used for DynInst, then this function
2001061SN/A// itself can handle returning the instruction's physical registers to
2011060SN/A// the free list.
2022292SN/Atemplate<class Impl>
2031060SN/Avoid
2041060SN/ASimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
2051060SN/A{
2061060SN/A    DPRINTF(Rename, "Rename: Removing a committed instruction from the "
2071060SN/A            "history buffer, until sequence number %lli.\n", inst_seq_num);
2081060SN/A    typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
2091060SN/A
2101061SN/A    --hb_it;
2111060SN/A
2129427SAndreas.Sandberg@ARM.com    if (hb_it->instSeqNum > inst_seq_num) {
2131060SN/A        DPRINTF(Rename, "Rename: Old sequence number encountered.  Ensure "
2149444SAndreas.Sandberg@ARM.com                "that a syscall happened recently.\n");
2159444SAndreas.Sandberg@ARM.com        return;
2169444SAndreas.Sandberg@ARM.com    }
2179444SAndreas.Sandberg@ARM.com
2189444SAndreas.Sandberg@ARM.com    while ((*hb_it).instSeqNum != inst_seq_num)
2199444SAndreas.Sandberg@ARM.com    {
2209444SAndreas.Sandberg@ARM.com        // Make sure we haven't gone off the end of the list.
2219444SAndreas.Sandberg@ARM.com        assert(hb_it != historyBuffer.end());
2229444SAndreas.Sandberg@ARM.com
2239444SAndreas.Sandberg@ARM.com        // In theory instructions at the end of the history buffer
2249444SAndreas.Sandberg@ARM.com        // should be older than the instruction being removed, which
2259444SAndreas.Sandberg@ARM.com        // means they will have a lower sequence number.  Also the
2262329SN/A        // instruction being removed from the history really should
2276221Snate@binkert.org        // be the last instruction in the list, as it is the instruction
2289444SAndreas.Sandberg@ARM.com        // that was just committed that is being removed.
2299444SAndreas.Sandberg@ARM.com        assert(hb_it->instSeqNum < inst_seq_num);
2302292SN/A        DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence"
2312292SN/A                " number %i.\n",
2322292SN/A                (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
2332292SN/A
2349444SAndreas.Sandberg@ARM.com        if (!(*hb_it).placeHolder) {
2359444SAndreas.Sandberg@ARM.com            freeList->addReg((*hb_it).prevPhysReg);
2369444SAndreas.Sandberg@ARM.com        }
2379444SAndreas.Sandberg@ARM.com
2389444SAndreas.Sandberg@ARM.com        historyBuffer.erase(hb_it--);
2399444SAndreas.Sandberg@ARM.com    }
2409444SAndreas.Sandberg@ARM.com
2419444SAndreas.Sandberg@ARM.com    // Finally free up the previous register of the squashed instruction
2422292SN/A    // itself.
2431060SN/A    if (!(*hb_it).placeHolder) {
2441060SN/A        freeList->addReg(hb_it->prevPhysReg);
2452292SN/A    }
2462292SN/A
2476221Snate@binkert.org    historyBuffer.erase(hb_it);
2482292SN/A
2492292SN/A}
2502292SN/A
2512292SN/Atemplate <class Impl>
2522292SN/Ainline void
2531061SN/ASimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst)
2541060SN/A{
2552292SN/A    unsigned num_src_regs = inst->numSrcRegs();
2561060SN/A
2576221Snate@binkert.org    // Get the architectual register numbers from the source and
2586221Snate@binkert.org    // destination operands, and redirect them to the right register.
2591060SN/A    // Will need to mark dependencies though.
2601060SN/A    for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
2611061SN/A    {
2621060SN/A        RegIndex src_reg = inst->srcRegIdx(src_idx);
2632292SN/A
2641060SN/A        // Look up the source registers to get the phys. register they've
2652292SN/A        // been renamed to, and set the sources to those registers.
2662292SN/A        RegIndex renamed_reg = renameMap->lookup(src_reg);
2671060SN/A
2682292SN/A        DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
2692292SN/A                "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
2702292SN/A
2712292SN/A        inst->renameSrcReg(src_idx, renamed_reg);
2722292SN/A
2731060SN/A        // Either incorporate it into the info passed back,
2741060SN/A        // or make another function call to see if that register is
2751061SN/A        // ready or not.
2762863Sktlim@umich.edu        if (renameMap->isReady(renamed_reg)) {
2779444SAndreas.Sandberg@ARM.com            DPRINTF(Rename, "Rename: Register is ready.\n");
2781060SN/A
2799444SAndreas.Sandberg@ARM.com            inst->markSrcRegReady(src_idx);
2809444SAndreas.Sandberg@ARM.com        }
2819444SAndreas.Sandberg@ARM.com    }
2829444SAndreas.Sandberg@ARM.com}
2839444SAndreas.Sandberg@ARM.com
2849444SAndreas.Sandberg@ARM.comtemplate <class Impl>
2859444SAndreas.Sandberg@ARM.cominline void
2862863Sktlim@umich.eduSimpleRename<Impl>::renameDestRegs(DynInstPtr &inst)
2872316SN/A{
2881060SN/A    typename SimpleRenameMap::RenameInfo rename_result;
2892316SN/A
2902316SN/A    unsigned num_dest_regs = inst->numDestRegs();
2912307SN/A
2921060SN/A    // Rename the destination registers.
2939444SAndreas.Sandberg@ARM.com    for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
2949444SAndreas.Sandberg@ARM.com    {
2951060SN/A        RegIndex dest_reg = inst->destRegIdx(dest_idx);
2969444SAndreas.Sandberg@ARM.com
2979444SAndreas.Sandberg@ARM.com        // Get the physical register that the destination will be
2989444SAndreas.Sandberg@ARM.com        // renamed to.
2999444SAndreas.Sandberg@ARM.com        rename_result = renameMap->rename(dest_reg);
3006221Snate@binkert.org
3019444SAndreas.Sandberg@ARM.com        DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
3029444SAndreas.Sandberg@ARM.com                "reg %i.\n", (int)dest_reg,
3039444SAndreas.Sandberg@ARM.com                (int)rename_result.first);
3049444SAndreas.Sandberg@ARM.com
3052307SN/A        // Record the rename information so that a history can be kept.
3062307SN/A        RenameHistory hb_entry(inst->seqNum, dest_reg,
3072307SN/A                               rename_result.first,
3082307SN/A                               rename_result.second);
3092307SN/A
3106221Snate@binkert.org        historyBuffer.push_front(hb_entry);
3111858SN/A
3122292SN/A        DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
3131858SN/A                "sequence number %lli.\n",
3142292SN/A                (*historyBuffer.begin()).instSeqNum);
3152292SN/A
3162292SN/A        // Tell the instruction to rename the appropriate destination
3172292SN/A        // register (dest_idx) to the new physical register
3183788Sgblack@eecs.umich.edu        // (rename_result.first), and record the previous physical
3192292SN/A        // register that the same logical register was renamed to
3202698Sktlim@umich.edu        // (rename_result.second).
3213788Sgblack@eecs.umich.edu        inst->renameDestReg(dest_idx,
3222301SN/A                            rename_result.first,
3233788Sgblack@eecs.umich.edu                            rename_result.second);
3243788Sgblack@eecs.umich.edu    }
3253788Sgblack@eecs.umich.edu
3263788Sgblack@eecs.umich.edu    // If it's an instruction with no destination registers, then put
3273788Sgblack@eecs.umich.edu    // a placeholder within the history buffer.  It might be better
3283788Sgblack@eecs.umich.edu    // to not put it in the history buffer at all (other than branches,
3293788Sgblack@eecs.umich.edu    // which always need at least a place holder), and differentiate
3303788Sgblack@eecs.umich.edu    // between instructions with and without destination registers
3313788Sgblack@eecs.umich.edu    // when getting from commit the instructions that committed.
3323788Sgblack@eecs.umich.edu    if (num_dest_regs == 0) {
3333788Sgblack@eecs.umich.edu        RenameHistory hb_entry(inst->seqNum);
3342292SN/A
3352292SN/A        historyBuffer.push_front(hb_entry);
3362292SN/A
3372292SN/A        DPRINTF(Rename, "Rename: Adding placeholder instruction to "
3382292SN/A                "history buffer, sequence number %lli.\n",
3392329SN/A                inst->seqNum);
3402292SN/A    }
3412292SN/A}
3422292SN/A
3432935Sksewell@umich.edutemplate <class Impl>
3442935Sksewell@umich.eduinline int
3452731Sktlim@umich.eduSimpleRename<Impl>::calcFreeROBEntries()
3462292SN/A{
3472292SN/A    return fromCommit->commitInfo.freeROBEntries -
3482292SN/A        renameWidth * iewToRenameDelay;
3492935Sksewell@umich.edu}
3502292SN/A
3512292SN/Atemplate <class Impl>
3522935Sksewell@umich.eduinline int
3534632Sgblack@eecs.umich.eduSimpleRename<Impl>::calcFreeIQEntries()
3543093Sksewell@umich.edu{
3552292SN/A    return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;
3562292SN/A}
3573093Sksewell@umich.edu
3584632Sgblack@eecs.umich.edutemplate<class Impl>
3592935Sksewell@umich.eduvoid
3602292SN/ASimpleRename<Impl>::tick()
3612292SN/A{
3622292SN/A    // Rename will need to try to rename as many instructions as it
3632292SN/A    // has bandwidth, unless it is blocked.
3642292SN/A
3652292SN/A    // Check if _status is BarrierStall.  If so, then check if the number
3662292SN/A    // of free ROB entries is equal to the number of total ROB entries.
3672292SN/A    // Once equal then wake this stage up.  Set status to unblocking maybe.
3682292SN/A
3692292SN/A    if (_status != Blocked && _status != Squashing) {
3702292SN/A        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "
3712292SN/A                        "run stage.\n");
3722292SN/A        // Make sure that the skid buffer has something in it if the
3732292SN/A        // status is unblocking.
3742292SN/A        assert(_status == Unblocking ? !skidBuffer.empty() : 1);
3752292SN/A
3766221Snate@binkert.org        rename();
3776221Snate@binkert.org
3782292SN/A        // If the status was unblocking, then instructions from the skid
3792292SN/A        // buffer were used.  Remove those instructions and handle
3803867Sbinkertn@umich.edu        // the rest of unblocking.
3816221Snate@binkert.org        if (_status == Unblocking) {
3822292SN/A            if (fromDecode->size > 0) {
3832292SN/A                // Add the current inputs onto the skid buffer, so they can be
3842292SN/A                // reprocessed when this stage unblocks.
3852292SN/A                skidBuffer.push(*fromDecode);
3862292SN/A            }
3872292SN/A
3882292SN/A            unblock();
3892292SN/A        }
3902292SN/A    } else if (_status == Blocked) {
3912292SN/A        // If stage is blocked and still receiving valid instructions,
3922292SN/A        // make sure to store them in the skid buffer.
3932292SN/A        if (fromDecode->size > 0) {
3942292SN/A
3952292SN/A            block();
3962292SN/A
3972292SN/A            // Continue to tell previous stage to stall.
3982292SN/A            toDecode->renameInfo.stall = true;
3993867Sbinkertn@umich.edu        }
4002292SN/A
4013867Sbinkertn@umich.edu        if (!fromIEW->iewInfo.stall &&
4026221Snate@binkert.org            !fromCommit->commitInfo.stall &&
4032292SN/A            calcFreeROBEntries() > 0 &&
4042292SN/A            calcFreeIQEntries() > 0 &&
4052292SN/A            renameMap->numFreeEntries() > 0) {
4062292SN/A
4072292SN/A            // Need to be sure to check all blocking conditions above.
4082292SN/A            // If they have cleared, then start unblocking.
4092292SN/A            DPRINTF(Rename, "Rename: Stall signals cleared, going to "
4102292SN/A                    "unblock.\n");
4112292SN/A            _status = Unblocking;
4122292SN/A
4132292SN/A            // Continue to tell previous stage to block until this stage
4142292SN/A            // is done unblocking.
4156221Snate@binkert.org            toDecode->renameInfo.stall = true;
4162292SN/A        } else {
4172292SN/A            // Otherwise no conditions have changed.  Tell previous
4182292SN/A            // stage to continue blocking.
4192292SN/A            toDecode->renameInfo.stall = true;
4202292SN/A        }
4212292SN/A
4222292SN/A        if (fromCommit->commitInfo.squash ||
4232292SN/A            fromCommit->commitInfo.robSquashing) {
4242292SN/A            squash();
4256221Snate@binkert.org            return;
4262292SN/A        }
4272292SN/A    } else if (_status == Squashing) {
4282292SN/A        if (fromCommit->commitInfo.squash) {
4292292SN/A            squash();
4302292SN/A        } else if (!fromCommit->commitInfo.squash &&
4312292SN/A                   !fromCommit->commitInfo.robSquashing) {
4322292SN/A
4332292SN/A            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");
4342292SN/A            _status = Running;
4352292SN/A        } else {
4362292SN/A            doSquash();
4372292SN/A        }
4382301SN/A    }
4392301SN/A
4403788Sgblack@eecs.umich.edu    // Ugly code, revamp all of the tick() functions eventually.
4413788Sgblack@eecs.umich.edu    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {
4423788Sgblack@eecs.umich.edu        removeFromHistory(fromCommit->commitInfo.doneSeqNum);
4433788Sgblack@eecs.umich.edu    }
4443788Sgblack@eecs.umich.edu
4453788Sgblack@eecs.umich.edu    // Perhaps put this outside of this function, since this will
4463788Sgblack@eecs.umich.edu    // happen regardless of whether or not the stage is blocked or
4473788Sgblack@eecs.umich.edu    // squashing.
4483798Sgblack@eecs.umich.edu    // Read from the time buffer any necessary data.
4493798Sgblack@eecs.umich.edu    // Read registers that are freed, and add them to the freelist.
4503798Sgblack@eecs.umich.edu    // This is unnecessary due to the history buffer (assuming the history
4513798Sgblack@eecs.umich.edu    // buffer works properly).
4523798Sgblack@eecs.umich.edu/*
4533798Sgblack@eecs.umich.edu    while(!fromCommit->commitInfo.freeRegs.empty())
4542292SN/A    {
4552292SN/A        PhysRegIndex freed_reg = fromCommit->commitInfo.freeRegs.back();
4562292SN/A        DPRINTF(Rename, "Rename: Adding freed register %i to freelist.\n",
4572292SN/A                (int)freed_reg);
4582292SN/A        freeList->addReg(freed_reg);
4592292SN/A
4602292SN/A        fromCommit->commitInfo.freeRegs.pop_back();
4612292SN/A    }
4622292SN/A*/
4632292SN/A
4642292SN/A}
4652292SN/A
4662292SN/Atemplate<class Impl>
4672292SN/Avoid
4682292SN/ASimpleRename<Impl>::rename()
4692292SN/A{
4702292SN/A    // Check if any of the stages ahead of rename are telling rename
4712292SN/A    // to squash.  The squash() function will also take care of fixing up
4722292SN/A    // the rename map and the free list.
4732292SN/A    if (fromCommit->commitInfo.squash ||
4741858SN/A        fromCommit->commitInfo.robSquashing) {
4751858SN/A        DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");
4761858SN/A        squash();
4771858SN/A        return;
4781858SN/A    }
4796221Snate@binkert.org
4801858SN/A    // Check if time buffer is telling this stage to stall.
4812292SN/A    if (fromIEW->iewInfo.stall ||
4822292SN/A        fromCommit->commitInfo.stall) {
4832292SN/A        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "
4842292SN/A                        "stall.\n");
4851858SN/A        block();
4862292SN/A        return;
4872292SN/A    }
4882292SN/A
4892292SN/A    // Check if the current status is squashing.  If so, set its status
4902292SN/A    // to running and resume execution the next cycle.
4912292SN/A    if (_status == Squashing) {
4922292SN/A        DPRINTF(Rename, "Rename: Done squashing.\n");
4932292SN/A        _status = Running;
4942292SN/A        return;
4952292SN/A    }
4962292SN/A
4972292SN/A    // Check the decode queue to see if instructions are available.
4982292SN/A    // If there are no available instructions to rename, then do nothing.
4991858SN/A    // Or, if the stage is currently unblocking, then go ahead and run it.
5002292SN/A    if (fromDecode->size == 0 && _status != Unblocking) {
5012292SN/A        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
5022292SN/A        // Should I change status to idle?
5032292SN/A        return;
5042292SN/A    }
5052292SN/A
5062292SN/A    ////////////////////////////////////
5072292SN/A    // Actual rename part.
5082292SN/A    ////////////////////////////////////
5092292SN/A
5102292SN/A    DynInstPtr inst;
5112292SN/A
5122292SN/A    // If we're unblocking, then we may be in the middle of an instruction
5132292SN/A    // group.  Subtract off numInst to get the proper number of instructions
5142292SN/A    // left.
5152292SN/A    int insts_available = _status == Unblocking ?
5162292SN/A        skidBuffer.front().size - numInst :
5172292SN/A        fromDecode->size;
5182292SN/A
5192292SN/A    bool block_this_cycle = false;
5202292SN/A
5212292SN/A    // Will have to do a different calculation for the number of free
5222292SN/A    // entries.  Number of free entries recorded on this cycle -
5232292SN/A    // renameWidth * renameToDecodeDelay
5242292SN/A    int free_rob_entries = calcFreeROBEntries();
5252292SN/A    int free_iq_entries = calcFreeIQEntries();
5262292SN/A    int min_iq_rob = min(free_rob_entries, free_iq_entries);
5272292SN/A
5282292SN/A    unsigned to_iew_index = 0;
5292292SN/A
5302292SN/A    // Check if there's any space left.
5312292SN/A    if (min_iq_rob <= 0) {
5322292SN/A        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
5332292SN/A                "entries.\n"
5342292SN/A                "Rename: ROB has %d free entries.\n"
5352292SN/A                "Rename: IQ has %d free entries.\n",
5362292SN/A                free_rob_entries,
5372292SN/A                free_iq_entries);
5382292SN/A        block();
5392292SN/A        // Tell previous stage to stall.
5402292SN/A        toDecode->renameInfo.stall = true;
5412292SN/A
5422292SN/A        return;
5432292SN/A    } else if (min_iq_rob < insts_available) {
5442292SN/A        DPRINTF(Rename, "Rename: Will have to block this cycle.  Only "
5452292SN/A                "%i insts can be renamed due to IQ/ROB limits.\n",
5462292SN/A                min_iq_rob);
5472292SN/A
5482292SN/A        insts_available = min_iq_rob;
5492292SN/A
5502292SN/A        block_this_cycle = true;
5512292SN/A    }
5522292SN/A
5532292SN/A    while (insts_available > 0) {
5542292SN/A        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
5552292SN/A
5562292SN/A        // Get the next instruction either from the skid buffer or the
5572292SN/A        // decode queue.
5582292SN/A        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
5592292SN/A               fromDecode->insts[numInst];
5602292SN/A
5612292SN/A        if (inst->isSquashed()) {
5622292SN/A            DPRINTF(Rename, "Rename: instruction %i with PC %#x is "
5632292SN/A                    "squashed, skipping.\n",
5642292SN/A                    inst->seqNum, inst->readPC());
5652292SN/A
5662292SN/A            // Go to the next instruction.
5672292SN/A            ++numInst;
5682292SN/A
5692292SN/A            // Decrement how many instructions are available.
5702292SN/A            --insts_available;
5712292SN/A
5722292SN/A            continue;
5732292SN/A        }
5742292SN/A
5752292SN/A        DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
5762292SN/A                inst->seqNum, inst->readPC());
5772292SN/A
5782292SN/A        // If it's a trap instruction, then it needs to wait here within
5792292SN/A        // rename until the ROB is empty.  Needs a way to detect that the
5802292SN/A        // ROB is empty.  Maybe an event?
5812292SN/A        // Would be nice if it could be avoided putting this into a
5822292SN/A        // specific stage and instead just put it into the AlphaFullCPU.
5832292SN/A        // Might not really be feasible though...
5842292SN/A        // (EXCB, TRAPB)
5857720Sgblack@eecs.umich.edu        if (inst->isSerializing()) {
5867720Sgblack@eecs.umich.edu            panic("Rename: Serializing instruction encountered.\n");
5872292SN/A            DPRINTF(Rename, "Rename: Serializing instruction "
5882292SN/A                            "encountered.\n");
5892292SN/A
5907720Sgblack@eecs.umich.edu            // Change status over to BarrierStall so that other stages know
5917720Sgblack@eecs.umich.edu            // what this is blocked on.
5927720Sgblack@eecs.umich.edu            _status = BarrierStall;
5932292SN/A
5942292SN/A            block_this_cycle = true;
5952292SN/A
5962292SN/A            break;
5972292SN/A        }
5982292SN/A
5992292SN/A        // Check here to make sure there are enough destination registers
6002292SN/A        // to rename to.  Otherwise block.
6012292SN/A        if (renameMap->numFreeEntries() < inst->numDestRegs())
6022292SN/A        {
6037720Sgblack@eecs.umich.edu            DPRINTF(Rename, "Rename: Blocking due to lack of free "
6042292SN/A                            "physical registers to rename to.\n");
6059531Sgeoffrey.blake@arm.com            // Need some sort of event based on a register being freed.
6069531Sgeoffrey.blake@arm.com
6079531Sgeoffrey.blake@arm.com            block_this_cycle = true;
6089531Sgeoffrey.blake@arm.com
6099531Sgeoffrey.blake@arm.com            break;
6109531Sgeoffrey.blake@arm.com        }
6119531Sgeoffrey.blake@arm.com
6129531Sgeoffrey.blake@arm.com        renameSrcRegs(inst);
6139531Sgeoffrey.blake@arm.com
6149531Sgeoffrey.blake@arm.com        renameDestRegs(inst);
6159531Sgeoffrey.blake@arm.com
6169531Sgeoffrey.blake@arm.com        // Put instruction in rename queue.
6172292SN/A        toIEW->insts[to_iew_index] = inst;
6182292SN/A        ++(toIEW->size);
6192292SN/A
6202292SN/A        // Decrease the number of free ROB and IQ entries.
6212336SN/A        --free_rob_entries;
6222336SN/A        --free_iq_entries;
6232336SN/A
6242336SN/A        // Increment which instruction we're on.
6252336SN/A        ++to_iew_index;
6262336SN/A        ++numInst;
6272336SN/A
6282336SN/A        // Decrement how many instructions are available.
6292292SN/A        --insts_available;
6302292SN/A    }
6312301SN/A
6322301SN/A    // Check if there's any instructions left that haven't yet been renamed.
6332292SN/A    // If so then block.
6342301SN/A    if (block_this_cycle) {
6352301SN/A        block();
6362301SN/A
6372292SN/A        toDecode->renameInfo.stall = true;
6382301SN/A    } else {
6392292SN/A        // If we had a successful rename and didn't have to exit early, then
6402301SN/A        // reset numInst so it will refer to the correct instruction on next
6412292SN/A        // run.
6422301SN/A        numInst = 0;
6432292SN/A    }
6442292SN/A}
6452292SN/A