rename_impl.hh revision 1858
17732SAli.Saidi@ARM.com/*
27732SAli.Saidi@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
37732SAli.Saidi@ARM.com * All rights reserved.
47732SAli.Saidi@ARM.com *
57732SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67732SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77732SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87732SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97732SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107732SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117732SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127732SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137732SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147732SAli.Saidi@ARM.com * this software without specific prior written permission.
157732SAli.Saidi@ARM.com *
167732SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177732SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187732SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197732SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207732SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217732SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227732SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237732SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247732SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257732SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267732SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277732SAli.Saidi@ARM.com */
287732SAli.Saidi@ARM.com
297732SAli.Saidi@ARM.com#include <list>
307732SAli.Saidi@ARM.com
317732SAli.Saidi@ARM.com#include "config/full_system.hh"
327732SAli.Saidi@ARM.com#include "cpu/o3/rename.hh"
337732SAli.Saidi@ARM.com
347732SAli.Saidi@ARM.comtemplate <class Impl>
357732SAli.Saidi@ARM.comSimpleRename<Impl>::SimpleRename(Params &params)
367732SAli.Saidi@ARM.com    : iewToRenameDelay(params.iewToRenameDelay),
377732SAli.Saidi@ARM.com      decodeToRenameDelay(params.decodeToRenameDelay),
387732SAli.Saidi@ARM.com      commitToRenameDelay(params.commitToRenameDelay),
397732SAli.Saidi@ARM.com      renameWidth(params.renameWidth),
407732SAli.Saidi@ARM.com      commitWidth(params.commitWidth),
417732SAli.Saidi@ARM.com      numInst(0)
428204SAli.Saidi@ARM.com{
438204SAli.Saidi@ARM.com    _status = Idle;
448204SAli.Saidi@ARM.com}
458204SAli.Saidi@ARM.com
468204SAli.Saidi@ARM.comtemplate <class Impl>
478204SAli.Saidi@ARM.comvoid
488204SAli.Saidi@ARM.comSimpleRename<Impl>::regStats()
498204SAli.Saidi@ARM.com{
508204SAli.Saidi@ARM.com    renameSquashCycles
518204SAli.Saidi@ARM.com        .name(name() + ".renameSquashCycles")
528204SAli.Saidi@ARM.com        .desc("Number of cycles rename is squashing")
538204SAli.Saidi@ARM.com        .prereq(renameSquashCycles);
548204SAli.Saidi@ARM.com    renameIdleCycles
557732SAli.Saidi@ARM.com        .name(name() + ".renameIdleCycles")
567732SAli.Saidi@ARM.com        .desc("Number of cycles rename is idle")
577732SAli.Saidi@ARM.com        .prereq(renameIdleCycles);
587732SAli.Saidi@ARM.com    renameBlockCycles
597732SAli.Saidi@ARM.com        .name(name() + ".renameBlockCycles")
607732SAli.Saidi@ARM.com        .desc("Number of cycles rename is blocking")
617732SAli.Saidi@ARM.com        .prereq(renameBlockCycles);
627732SAli.Saidi@ARM.com    renameUnblockCycles
637732SAli.Saidi@ARM.com        .name(name() + ".renameUnblockCycles")
647732SAli.Saidi@ARM.com        .desc("Number of cycles rename is unblocking")
657732SAli.Saidi@ARM.com        .prereq(renameUnblockCycles);
667732SAli.Saidi@ARM.com    renameRenamedInsts
677732SAli.Saidi@ARM.com        .name(name() + ".renameRenamedInsts")
687732SAli.Saidi@ARM.com        .desc("Number of instructions processed by rename")
697732SAli.Saidi@ARM.com        .prereq(renameRenamedInsts);
707732SAli.Saidi@ARM.com    renameSquashedInsts
718204SAli.Saidi@ARM.com        .name(name() + ".renameSquashedInsts")
727732SAli.Saidi@ARM.com        .desc("Number of squashed instructions processed by rename")
737732SAli.Saidi@ARM.com        .prereq(renameSquashedInsts);
747732SAli.Saidi@ARM.com    renameROBFullEvents
757732SAli.Saidi@ARM.com        .name(name() + ".renameROBFullEvents")
767732SAli.Saidi@ARM.com        .desc("Number of times rename has considered the ROB 'full'")
777732SAli.Saidi@ARM.com        .prereq(renameROBFullEvents);
787732SAli.Saidi@ARM.com    renameIQFullEvents
797732SAli.Saidi@ARM.com        .name(name() + ".renameIQFullEvents")
808142SAli.Saidi@ARM.com        .desc("Number of times rename has considered the IQ 'full'")
817732SAli.Saidi@ARM.com        .prereq(renameIQFullEvents);
827732SAli.Saidi@ARM.com    renameFullRegistersEvents
837732SAli.Saidi@ARM.com        .name(name() + ".renameFullRegisterEvents")
848204SAli.Saidi@ARM.com        .desc("Number of times there has been no free registers")
857732SAli.Saidi@ARM.com        .prereq(renameFullRegistersEvents);
867732SAli.Saidi@ARM.com    renameRenamedOperands
877732SAli.Saidi@ARM.com        .name(name() + ".renameRenamedOperands")
887732SAli.Saidi@ARM.com        .desc("Number of destination operands rename has renamed")
897732SAli.Saidi@ARM.com        .prereq(renameRenamedOperands);
907732SAli.Saidi@ARM.com    renameRenameLookups
917732SAli.Saidi@ARM.com        .name(name() + ".renameRenameLookups")
927732SAli.Saidi@ARM.com        .desc("Number of register rename lookups that rename has made")
937732SAli.Saidi@ARM.com        .prereq(renameRenameLookups);
948142SAli.Saidi@ARM.com    renameHBPlaceHolders
957732SAli.Saidi@ARM.com        .name(name() + ".renameHBPlaceHolders")
967732SAli.Saidi@ARM.com        .desc("Number of place holders added to the history buffer")
977732SAli.Saidi@ARM.com        .prereq(renameHBPlaceHolders);
988204SAli.Saidi@ARM.com    renameCommittedMaps
997732SAli.Saidi@ARM.com        .name(name() + ".renameCommittedMaps")
1007732SAli.Saidi@ARM.com        .desc("Number of HB maps that are committed")
1017732SAli.Saidi@ARM.com        .prereq(renameCommittedMaps);
1027732SAli.Saidi@ARM.com    renameUndoneMaps
1037732SAli.Saidi@ARM.com        .name(name() + ".renameUndoneMaps")
1047732SAli.Saidi@ARM.com        .desc("Number of HB maps that are undone due to squashing")
1057732SAli.Saidi@ARM.com        .prereq(renameUndoneMaps);
1067732SAli.Saidi@ARM.com    renameValidUndoneMaps
1077732SAli.Saidi@ARM.com        .name(name() + ".renameValidUndoneMaps")
1088142SAli.Saidi@ARM.com        .desc("Number of HB maps that are undone, and are not place holders")
1097732SAli.Saidi@ARM.com        .prereq(renameValidUndoneMaps);
1107732SAli.Saidi@ARM.com}
1117732SAli.Saidi@ARM.com
1128204SAli.Saidi@ARM.comtemplate <class Impl>
1138204SAli.Saidi@ARM.comvoid
1148204SAli.Saidi@ARM.comSimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
1157732SAli.Saidi@ARM.com{
1167732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Setting CPU pointer.\n");
1177732SAli.Saidi@ARM.com    cpu = cpu_ptr;
1187732SAli.Saidi@ARM.com}
1197732SAli.Saidi@ARM.com
1207732SAli.Saidi@ARM.comtemplate <class Impl>
1217732SAli.Saidi@ARM.comvoid
1227732SAli.Saidi@ARM.comSimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1237732SAli.Saidi@ARM.com{
1247732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Setting time buffer pointer.\n");
1257732SAli.Saidi@ARM.com    timeBuffer = tb_ptr;
1268204SAli.Saidi@ARM.com
1278204SAli.Saidi@ARM.com    // Setup wire to read information from time buffer, from IEW stage.
1288204SAli.Saidi@ARM.com    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
1298204SAli.Saidi@ARM.com
1308204SAli.Saidi@ARM.com    // Setup wire to read infromation from time buffer, from commit stage.
1318204SAli.Saidi@ARM.com    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
1327732SAli.Saidi@ARM.com
1338204SAli.Saidi@ARM.com    // Setup wire to write information to previous stages.
1347732SAli.Saidi@ARM.com    toDecode = timeBuffer->getWire(0);
1357732SAli.Saidi@ARM.com}
1367732SAli.Saidi@ARM.com
1377732SAli.Saidi@ARM.comtemplate <class Impl>
1387732SAli.Saidi@ARM.comvoid
1397732SAli.Saidi@ARM.comSimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
1408204SAli.Saidi@ARM.com{
1418204SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Setting rename queue pointer.\n");
1428204SAli.Saidi@ARM.com    renameQueue = rq_ptr;
1438204SAli.Saidi@ARM.com
1447732SAli.Saidi@ARM.com    // Setup wire to write information to future stages.
1458204SAli.Saidi@ARM.com    toIEW = renameQueue->getWire(0);
1468204SAli.Saidi@ARM.com}
1478204SAli.Saidi@ARM.com
1487732SAli.Saidi@ARM.comtemplate <class Impl>
1497732SAli.Saidi@ARM.comvoid
1507732SAli.Saidi@ARM.comSimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
1517732SAli.Saidi@ARM.com{
1527732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Setting decode queue pointer.\n");
1537732SAli.Saidi@ARM.com    decodeQueue = dq_ptr;
1547732SAli.Saidi@ARM.com
1557732SAli.Saidi@ARM.com    // Setup wire to get information from decode.
1567732SAli.Saidi@ARM.com    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
1577732SAli.Saidi@ARM.com}
1587732SAli.Saidi@ARM.com
1597732SAli.Saidi@ARM.comtemplate <class Impl>
1607732SAli.Saidi@ARM.comvoid
1617732SAli.Saidi@ARM.comSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
1627732SAli.Saidi@ARM.com{
1637732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Setting rename map pointer.\n");
1647732SAli.Saidi@ARM.com    renameMap = rm_ptr;
1657732SAli.Saidi@ARM.com}
1667732SAli.Saidi@ARM.com
1677732SAli.Saidi@ARM.comtemplate <class Impl>
1687732SAli.Saidi@ARM.comvoid
1697732SAli.Saidi@ARM.comSimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
1707732SAli.Saidi@ARM.com{
1717732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Setting free list pointer.\n");
1727732SAli.Saidi@ARM.com    freeList = fl_ptr;
1737732SAli.Saidi@ARM.com}
1747732SAli.Saidi@ARM.com
1757732SAli.Saidi@ARM.comtemplate <class Impl>
1767732SAli.Saidi@ARM.comvoid
1777732SAli.Saidi@ARM.comSimpleRename<Impl>::dumpHistory()
1787732SAli.Saidi@ARM.com{
1798204SAli.Saidi@ARM.com    typename list<RenameHistory>::iterator buf_it = historyBuffer.begin();
1808204SAli.Saidi@ARM.com
1818204SAli.Saidi@ARM.com    while (buf_it != historyBuffer.end())
1827732SAli.Saidi@ARM.com    {
1838204SAli.Saidi@ARM.com        cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1848204SAli.Saidi@ARM.com                "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1858204SAli.Saidi@ARM.com                (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1867732SAli.Saidi@ARM.com
1877732SAli.Saidi@ARM.com        buf_it++;
1887732SAli.Saidi@ARM.com    }
1897732SAli.Saidi@ARM.com}
1907732SAli.Saidi@ARM.com
1917732SAli.Saidi@ARM.comtemplate <class Impl>
1927732SAli.Saidi@ARM.comvoid
1937732SAli.Saidi@ARM.comSimpleRename<Impl>::block()
1947732SAli.Saidi@ARM.com{
1957732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Blocking.\n");
1967732SAli.Saidi@ARM.com    // Set status to Blocked.
1977732SAli.Saidi@ARM.com    _status = Blocked;
1987732SAli.Saidi@ARM.com
1997732SAli.Saidi@ARM.com    // Add the current inputs onto the skid buffer, so they can be
2007732SAli.Saidi@ARM.com    // reprocessed when this stage unblocks.
2017732SAli.Saidi@ARM.com    skidBuffer.push(*fromDecode);
2027732SAli.Saidi@ARM.com
2037732SAli.Saidi@ARM.com    // Note that this stage only signals previous stages to stall when
2047732SAli.Saidi@ARM.com    // it is the cause of the stall originates at this stage.  Otherwise
2057732SAli.Saidi@ARM.com    // the previous stages are expected to check all possible stall signals.
2067732SAli.Saidi@ARM.com}
2077732SAli.Saidi@ARM.com
2087732SAli.Saidi@ARM.comtemplate <class Impl>
2097732SAli.Saidi@ARM.cominline void
2107732SAli.Saidi@ARM.comSimpleRename<Impl>::unblock()
2117732SAli.Saidi@ARM.com{
2127732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Read instructions out of skid buffer this "
2137732SAli.Saidi@ARM.com            "cycle.\n");
2147732SAli.Saidi@ARM.com    // Remove the now processed instructions from the skid buffer.
2157732SAli.Saidi@ARM.com    skidBuffer.pop();
2167732SAli.Saidi@ARM.com
2178204SAli.Saidi@ARM.com    // If there's still information in the skid buffer, then
2188204SAli.Saidi@ARM.com    // continue to tell previous stages to stall.  They will be
2198204SAli.Saidi@ARM.com    // able to restart once the skid buffer is empty.
2208204SAli.Saidi@ARM.com    if (!skidBuffer.empty()) {
2217732SAli.Saidi@ARM.com        toDecode->renameInfo.stall = true;
2228204SAli.Saidi@ARM.com    } else {
2237732SAli.Saidi@ARM.com        DPRINTF(Rename, "Rename: Done unblocking.\n");
2247732SAli.Saidi@ARM.com        _status = Running;
2257732SAli.Saidi@ARM.com    }
2267732SAli.Saidi@ARM.com}
2277732SAli.Saidi@ARM.com
2287732SAli.Saidi@ARM.comtemplate <class Impl>
2298204SAli.Saidi@ARM.comvoid
2308204SAli.Saidi@ARM.comSimpleRename<Impl>::doSquash()
2318204SAli.Saidi@ARM.com{
2327732SAli.Saidi@ARM.com    typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
2338204SAli.Saidi@ARM.com
2347732SAli.Saidi@ARM.com    InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
2357732SAli.Saidi@ARM.com
2367732SAli.Saidi@ARM.com#if FULL_SYSTEM
2377732SAli.Saidi@ARM.com    assert(!historyBuffer.empty());
2387732SAli.Saidi@ARM.com#else
2397732SAli.Saidi@ARM.com    // After a syscall squashes everything, the history buffer may be empty
2408204SAli.Saidi@ARM.com    // but the ROB may still be squashing instructions.
2418204SAli.Saidi@ARM.com    if (historyBuffer.empty()) {
2428204SAli.Saidi@ARM.com        return;
2437732SAli.Saidi@ARM.com    }
2448204SAli.Saidi@ARM.com#endif // FULL_SYSTEM
2457732SAli.Saidi@ARM.com
2467732SAli.Saidi@ARM.com    // Go through the most recent instructions, undoing the mappings
2477732SAli.Saidi@ARM.com    // they did and freeing up the registers.
2487732SAli.Saidi@ARM.com    while ((*hb_it).instSeqNum > squashed_seq_num)
2497732SAli.Saidi@ARM.com    {
2507732SAli.Saidi@ARM.com        assert(hb_it != historyBuffer.end());
2518204SAli.Saidi@ARM.com
2528204SAli.Saidi@ARM.com        DPRINTF(Rename, "Rename: Removing history entry with sequence "
2538204SAli.Saidi@ARM.com                "number %i.\n", (*hb_it).instSeqNum);
2547732SAli.Saidi@ARM.com
2558204SAli.Saidi@ARM.com        // If it's not simply a place holder, then add the registers.
2567732SAli.Saidi@ARM.com        if (!(*hb_it).placeHolder) {
2577732SAli.Saidi@ARM.com            // Tell the rename map to set the architected register to the
2587732SAli.Saidi@ARM.com            // previous physical register that it was renamed to.
2597732SAli.Saidi@ARM.com            renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg);
2607732SAli.Saidi@ARM.com
2617732SAli.Saidi@ARM.com            // Put the renamed physical register back on the free list.
2627732SAli.Saidi@ARM.com            freeList->addReg(hb_it->newPhysReg);
2637732SAli.Saidi@ARM.com
2648204SAli.Saidi@ARM.com            ++renameValidUndoneMaps;
2658204SAli.Saidi@ARM.com        }
2668204SAli.Saidi@ARM.com
2677732SAli.Saidi@ARM.com        historyBuffer.erase(hb_it++);
2687732SAli.Saidi@ARM.com
2697732SAli.Saidi@ARM.com        ++renameUndoneMaps;
2707732SAli.Saidi@ARM.com    }
2717732SAli.Saidi@ARM.com}
2727732SAli.Saidi@ARM.com
2737732SAli.Saidi@ARM.comtemplate <class Impl>
2747732SAli.Saidi@ARM.comvoid
2757732SAli.Saidi@ARM.comSimpleRename<Impl>::squash()
2767732SAli.Saidi@ARM.com{
2777732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Squashing instructions.\n");
2787732SAli.Saidi@ARM.com    // Set the status to Squashing.
2797732SAli.Saidi@ARM.com    _status = Squashing;
2807732SAli.Saidi@ARM.com
2817732SAli.Saidi@ARM.com    numInst = 0;
2827732SAli.Saidi@ARM.com
2837732SAli.Saidi@ARM.com    // Clear the skid buffer in case it has any data in it.
2847732SAli.Saidi@ARM.com    while (!skidBuffer.empty())
2857732SAli.Saidi@ARM.com    {
2867732SAli.Saidi@ARM.com        skidBuffer.pop();
2877732SAli.Saidi@ARM.com    }
2887732SAli.Saidi@ARM.com
2897732SAli.Saidi@ARM.com    doSquash();
2907732SAli.Saidi@ARM.com}
2917732SAli.Saidi@ARM.com
2927732SAli.Saidi@ARM.comtemplate<class Impl>
2937732SAli.Saidi@ARM.comvoid
2947732SAli.Saidi@ARM.comSimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
2958204SAli.Saidi@ARM.com{
2967732SAli.Saidi@ARM.com    DPRINTF(Rename, "Rename: Removing a committed instruction from the "
2977732SAli.Saidi@ARM.com            "history buffer, until sequence number %lli.\n", inst_seq_num);
2987732SAli.Saidi@ARM.com    typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
2997732SAli.Saidi@ARM.com
3007732SAli.Saidi@ARM.com    --hb_it;
3017732SAli.Saidi@ARM.com
3027732SAli.Saidi@ARM.com    if (hb_it->instSeqNum > inst_seq_num) {
3037732SAli.Saidi@ARM.com        DPRINTF(Rename, "Rename: Old sequence number encountered.  Ensure "
3047732SAli.Saidi@ARM.com                "that a syscall happened recently.\n");
3057732SAli.Saidi@ARM.com        return;
3067732SAli.Saidi@ARM.com    }
3077732SAli.Saidi@ARM.com
3087732SAli.Saidi@ARM.com    while ((*hb_it).instSeqNum != inst_seq_num)
3097732SAli.Saidi@ARM.com    {
3107732SAli.Saidi@ARM.com        // Make sure we haven't gone off the end of the list.
3117732SAli.Saidi@ARM.com        assert(hb_it != historyBuffer.end());
3127732SAli.Saidi@ARM.com
3137732SAli.Saidi@ARM.com        // In theory instructions at the end of the history buffer
3147732SAli.Saidi@ARM.com        // should be older than the instruction being removed, which
3157732SAli.Saidi@ARM.com        // means they will have a lower sequence number.  Also the
3167732SAli.Saidi@ARM.com        // instruction being removed from the history really should
317        // be the last instruction in the list, as it is the instruction
318        // that was just committed that is being removed.
319        assert(hb_it->instSeqNum < inst_seq_num);
320        DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence"
321                " number %i.\n",
322                (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
323
324        if (!(*hb_it).placeHolder) {
325            freeList->addReg((*hb_it).prevPhysReg);
326            ++renameCommittedMaps;
327        }
328
329        historyBuffer.erase(hb_it--);
330    }
331
332    // Finally free up the previous register of the finished instruction
333    // itself.
334    if (!(*hb_it).placeHolder) {
335        freeList->addReg(hb_it->prevPhysReg);
336        ++renameCommittedMaps;
337    }
338
339    historyBuffer.erase(hb_it);
340}
341
342template <class Impl>
343inline void
344SimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst)
345{
346    unsigned num_src_regs = inst->numSrcRegs();
347
348    // Get the architectual register numbers from the source and
349    // destination operands, and redirect them to the right register.
350    // Will need to mark dependencies though.
351    for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
352    {
353        RegIndex src_reg = inst->srcRegIdx(src_idx);
354
355        // Look up the source registers to get the phys. register they've
356        // been renamed to, and set the sources to those registers.
357        PhysRegIndex renamed_reg = renameMap->lookup(src_reg);
358
359        DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
360                "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
361
362        inst->renameSrcReg(src_idx, renamed_reg);
363
364        // Either incorporate it into the info passed back,
365        // or make another function call to see if that register is
366        // ready or not.
367        if (renameMap->isReady(renamed_reg)) {
368            DPRINTF(Rename, "Rename: Register is ready.\n");
369
370            inst->markSrcRegReady(src_idx);
371        }
372
373        ++renameRenameLookups;
374    }
375}
376
377template <class Impl>
378inline void
379SimpleRename<Impl>::renameDestRegs(DynInstPtr &inst)
380{
381    typename SimpleRenameMap::RenameInfo rename_result;
382
383    unsigned num_dest_regs = inst->numDestRegs();
384
385    // If it's an instruction with no destination registers, then put
386    // a placeholder within the history buffer.  It might be better
387    // to not put it in the history buffer at all (other than branches,
388    // which always need at least a place holder), and differentiate
389    // between instructions with and without destination registers
390    // when getting from commit the instructions that committed.
391    if (num_dest_regs == 0) {
392        RenameHistory hb_entry(inst->seqNum);
393
394        historyBuffer.push_front(hb_entry);
395
396        DPRINTF(Rename, "Rename: Adding placeholder instruction to "
397                "history buffer, sequence number %lli.\n",
398                inst->seqNum);
399
400        ++renameHBPlaceHolders;
401    } else {
402
403        // Rename the destination registers.
404        for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
405        {
406            RegIndex dest_reg = inst->destRegIdx(dest_idx);
407
408            // Get the physical register that the destination will be
409            // renamed to.
410            rename_result = renameMap->rename(dest_reg);
411
412            DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
413                    "reg %i.\n", (int)dest_reg,
414                    (int)rename_result.first);
415
416            // Record the rename information so that a history can be kept.
417            RenameHistory hb_entry(inst->seqNum, dest_reg,
418                                   rename_result.first,
419                                   rename_result.second);
420
421            historyBuffer.push_front(hb_entry);
422
423            DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
424                    "sequence number %lli.\n",
425                    (*historyBuffer.begin()).instSeqNum);
426
427            // Tell the instruction to rename the appropriate destination
428            // register (dest_idx) to the new physical register
429            // (rename_result.first), and record the previous physical
430            // register that the same logical register was renamed to
431            // (rename_result.second).
432            inst->renameDestReg(dest_idx,
433                                rename_result.first,
434                                rename_result.second);
435
436            ++renameRenamedOperands;
437        }
438    }
439}
440
441template <class Impl>
442inline int
443SimpleRename<Impl>::calcFreeROBEntries()
444{
445    return fromCommit->commitInfo.freeROBEntries -
446        renameWidth * iewToRenameDelay;
447}
448
449template <class Impl>
450inline int
451SimpleRename<Impl>::calcFreeIQEntries()
452{
453    return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;
454}
455
456template<class Impl>
457void
458SimpleRename<Impl>::tick()
459{
460    // Rename will need to try to rename as many instructions as it
461    // has bandwidth, unless it is blocked.
462
463    // Check if _status is BarrierStall.  If so, then check if the number
464    // of free ROB entries is equal to the number of total ROB entries.
465    // Once equal then wake this stage up.  Set status to unblocking maybe.
466
467    if (_status != Blocked && _status != Squashing) {
468        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "
469                        "run stage.\n");
470        // Make sure that the skid buffer has something in it if the
471        // status is unblocking.
472        assert(_status == Unblocking ? !skidBuffer.empty() : 1);
473
474        rename();
475
476        // If the status was unblocking, then instructions from the skid
477        // buffer were used.  Remove those instructions and handle
478        // the rest of unblocking.
479        if (_status == Unblocking) {
480            ++renameUnblockCycles;
481
482            if (fromDecode->size > 0) {
483                // Add the current inputs onto the skid buffer, so they can be
484                // reprocessed when this stage unblocks.
485                skidBuffer.push(*fromDecode);
486            }
487
488            unblock();
489        }
490    } else if (_status == Blocked) {
491        ++renameBlockCycles;
492
493        // If stage is blocked and still receiving valid instructions,
494        // make sure to store them in the skid buffer.
495        if (fromDecode->size > 0) {
496
497            block();
498
499            // Continue to tell previous stage to stall.
500            toDecode->renameInfo.stall = true;
501        }
502
503        if (!fromIEW->iewInfo.stall &&
504            !fromCommit->commitInfo.stall &&
505            calcFreeROBEntries() > 0 &&
506            calcFreeIQEntries() > 0 &&
507            renameMap->numFreeEntries() > 0) {
508
509            // Need to be sure to check all blocking conditions above.
510            // If they have cleared, then start unblocking.
511            DPRINTF(Rename, "Rename: Stall signals cleared, going to "
512                    "unblock.\n");
513            _status = Unblocking;
514
515            // Continue to tell previous stage to block until this stage
516            // is done unblocking.
517            toDecode->renameInfo.stall = true;
518        } else {
519            // Otherwise no conditions have changed.  Tell previous
520            // stage to continue blocking.
521            toDecode->renameInfo.stall = true;
522        }
523
524        if (fromCommit->commitInfo.squash ||
525            fromCommit->commitInfo.robSquashing) {
526            squash();
527            return;
528        }
529    } else if (_status == Squashing) {
530        ++renameSquashCycles;
531
532        if (fromCommit->commitInfo.squash) {
533            squash();
534        } else if (!fromCommit->commitInfo.squash &&
535                   !fromCommit->commitInfo.robSquashing) {
536
537            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");
538            _status = Running;
539            rename();
540        } else {
541            doSquash();
542        }
543    }
544
545    // Ugly code, revamp all of the tick() functions eventually.
546    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {
547#if !FULL_SYSTEM
548        if (!fromCommit->commitInfo.squash) {
549            removeFromHistory(fromCommit->commitInfo.doneSeqNum);
550        }
551#else
552        removeFromHistory(fromCommit->commitInfo.doneSeqNum);
553#endif
554    }
555
556}
557
558template<class Impl>
559void
560SimpleRename<Impl>::rename()
561{
562    // Check if any of the stages ahead of rename are telling rename
563    // to squash.  The squash() function will also take care of fixing up
564    // the rename map and the free list.
565    if (fromCommit->commitInfo.squash ||
566        fromCommit->commitInfo.robSquashing) {
567        DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");
568        squash();
569        return;
570    }
571
572    // Check if time buffer is telling this stage to stall.
573    if (fromIEW->iewInfo.stall ||
574        fromCommit->commitInfo.stall) {
575        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "
576                        "stall.\n");
577        block();
578        return;
579    }
580
581    // Check if the current status is squashing.  If so, set its status
582    // to running and resume execution the next cycle.
583    if (_status == Squashing) {
584        DPRINTF(Rename, "Rename: Done squashing.\n");
585        _status = Running;
586        return;
587    }
588
589    // Check the decode queue to see if instructions are available.
590    // If there are no available instructions to rename, then do nothing.
591    // Or, if the stage is currently unblocking, then go ahead and run it.
592    if (fromDecode->size == 0 && _status != Unblocking) {
593        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
594        // Should I change status to idle?
595        return;
596    }
597
598    ////////////////////////////////////
599    // Actual rename part.
600    ////////////////////////////////////
601
602    DynInstPtr inst;
603
604    // If we're unblocking, then we may be in the middle of an instruction
605    // group.  Subtract off numInst to get the proper number of instructions
606    // left.
607    int insts_available = _status == Unblocking ?
608        skidBuffer.front().size - numInst :
609        fromDecode->size;
610
611    bool block_this_cycle = false;
612
613    // Will have to do a different calculation for the number of free
614    // entries.  Number of free entries recorded on this cycle -
615    // renameWidth * renameToDecodeDelay
616    int free_rob_entries = calcFreeROBEntries();
617    int free_iq_entries = calcFreeIQEntries();
618    int min_iq_rob = min(free_rob_entries, free_iq_entries);
619
620    unsigned to_iew_index = 0;
621
622    // Check if there's any space left.
623    if (min_iq_rob <= 0) {
624        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
625                "entries.\n"
626                "Rename: ROB has %d free entries.\n"
627                "Rename: IQ has %d free entries.\n",
628                free_rob_entries,
629                free_iq_entries);
630        block();
631        // Tell previous stage to stall.
632        toDecode->renameInfo.stall = true;
633
634        if (free_rob_entries <= 0) {
635            ++renameROBFullEvents;
636        } else {
637            ++renameIQFullEvents;
638        }
639
640        return;
641    } else if (min_iq_rob < insts_available) {
642        DPRINTF(Rename, "Rename: Will have to block this cycle.  Only "
643                "%i insts can be renamed due to IQ/ROB limits.\n",
644                min_iq_rob);
645
646        insts_available = min_iq_rob;
647
648        block_this_cycle = true;
649
650        if (free_rob_entries < free_iq_entries) {
651            ++renameROBFullEvents;
652        } else {
653            ++renameIQFullEvents;
654        }
655    }
656
657    while (insts_available > 0) {
658        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
659
660        // Get the next instruction either from the skid buffer or the
661        // decode queue.
662        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
663               fromDecode->insts[numInst];
664
665        if (inst->isSquashed()) {
666            DPRINTF(Rename, "Rename: instruction %i with PC %#x is "
667                    "squashed, skipping.\n",
668                    inst->seqNum, inst->readPC());
669
670            // Go to the next instruction.
671            ++numInst;
672
673            ++renameSquashedInsts;
674
675            // Decrement how many instructions are available.
676            --insts_available;
677
678            continue;
679        }
680
681        DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
682                inst->seqNum, inst->readPC());
683
684        // If it's a trap instruction, then it needs to wait here within
685        // rename until the ROB is empty.  Needs a way to detect that the
686        // ROB is empty.  Maybe an event?
687        // Would be nice if it could be avoided putting this into a
688        // specific stage and instead just put it into the AlphaFullCPU.
689        // Might not really be feasible though...
690        // (EXCB, TRAPB)
691        if (inst->isSerializing()) {
692            panic("Rename: Serializing instruction encountered.\n");
693            DPRINTF(Rename, "Rename: Serializing instruction "
694                            "encountered.\n");
695
696            // Change status over to BarrierStall so that other stages know
697            // what this is blocked on.
698            _status = BarrierStall;
699
700            block_this_cycle = true;
701
702            break;
703        }
704
705        // Check here to make sure there are enough destination registers
706        // to rename to.  Otherwise block.
707        if (renameMap->numFreeEntries() < inst->numDestRegs())
708        {
709            DPRINTF(Rename, "Rename: Blocking due to lack of free "
710                            "physical registers to rename to.\n");
711            // Need some sort of event based on a register being freed.
712
713            block_this_cycle = true;
714
715            ++renameFullRegistersEvents;
716
717            break;
718        }
719
720        renameSrcRegs(inst);
721
722        renameDestRegs(inst);
723
724        // Put instruction in rename queue.
725        toIEW->insts[to_iew_index] = inst;
726        ++(toIEW->size);
727
728        // Decrease the number of free ROB and IQ entries.
729        --free_rob_entries;
730        --free_iq_entries;
731
732        // Increment which instruction we're on.
733        ++to_iew_index;
734        ++numInst;
735
736        ++renameRenamedInsts;
737
738        // Decrement how many instructions are available.
739        --insts_available;
740    }
741
742    // Check if there's any instructions left that haven't yet been renamed.
743    // If so then block.
744    if (block_this_cycle) {
745        block();
746
747        toDecode->renameInfo.stall = true;
748    } else {
749        // If we had a successful rename and didn't have to exit early, then
750        // reset numInst so it will refer to the correct instruction on next
751        // run.
752        numInst = 0;
753    }
754}
755