rename_impl.hh revision 1060
12SN/A#include <list>
212284Sjose.marinho@arm.com
39920Syasuko.eckert@amd.com#include "cpu/beta_cpu/rename.hh"
47338SAli.Saidi@ARM.com
57338SAli.Saidi@ARM.comtemplate<class Impl>
67338SAli.Saidi@ARM.comSimpleRename<Impl>::SimpleRename(Params &params)
77338SAli.Saidi@ARM.com    : iewToRenameDelay(params.iewToRenameDelay),
87338SAli.Saidi@ARM.com      decodeToRenameDelay(params.decodeToRenameDelay),
97338SAli.Saidi@ARM.com      commitToRenameDelay(params.commitToRenameDelay),
107338SAli.Saidi@ARM.com      renameWidth(params.renameWidth),
117338SAli.Saidi@ARM.com      commitWidth(params.commitWidth)
127338SAli.Saidi@ARM.com{
137338SAli.Saidi@ARM.com    _status = Idle;
147338SAli.Saidi@ARM.com}
151762SN/A
162SN/Atemplate<class Impl>
172SN/Avoid
182SN/ASimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
192SN/A{
202SN/A    DPRINTF(Rename, "Rename: Setting CPU pointer.\n");
212SN/A    cpu = cpu_ptr;
222SN/A}
232SN/A
242SN/Atemplate<class Impl>
252SN/Avoid
262SN/ASimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
272SN/A{
282SN/A    DPRINTF(Rename, "Rename: Setting time buffer pointer.\n");
292SN/A    timeBuffer = tb_ptr;
302SN/A
312SN/A    // Setup wire to read information from time buffer, from IEW stage.
322SN/A    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
332SN/A
342SN/A    // Setup wire to read infromation from time buffer, from commit stage.
352SN/A    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
362SN/A
372SN/A    // Setup wire to write information to previous stages.
382SN/A    toDecode = timeBuffer->getWire(0);
392SN/A}
402665Ssaidi@eecs.umich.edu
412665Ssaidi@eecs.umich.edutemplate<class Impl>
422SN/Avoid
432SN/ASimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
4411793Sbrandon.potter@amd.com{
4511793Sbrandon.potter@amd.com    DPRINTF(Rename, "Rename: Setting rename queue pointer.\n");
468779Sgblack@eecs.umich.edu    renameQueue = rq_ptr;
478779Sgblack@eecs.umich.edu
482439SN/A    // Setup wire to write information to future stages.
498779Sgblack@eecs.umich.edu    toIEW = renameQueue->getWire(0);
506216Snate@binkert.org}
51146SN/A
52146SN/Atemplate<class Impl>
5311793Sbrandon.potter@amd.comvoid
5412334Sgabeblack@google.comSimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
55146SN/A{
56146SN/A    DPRINTF(Rename, "Rename: Setting decode queue pointer.\n");
576216Snate@binkert.org    decodeQueue = dq_ptr;
586658Snate@binkert.org
591717SN/A    // Setup wire to get information from decode.
608887Sgeoffrey.blake@arm.com    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
618887Sgeoffrey.blake@arm.com
62146SN/A}
6310061Sandreas@sandberg.pp.se
641977SN/Atemplate<class Impl>
6511147Smitch.hayenga@arm.comvoid
662683Sktlim@umich.eduSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
671717SN/A{
68146SN/A    DPRINTF(Rename, "Rename: Setting rename map pointer.\n");
692683Sktlim@umich.edu    renameMap = rm_ptr;
708232Snate@binkert.org}
718232Snate@binkert.org
728232Snate@binkert.orgtemplate<class Impl>
738779Sgblack@eecs.umich.eduvoid
743348Sbinkertn@umich.eduSimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
756105Ssteve.reinhardt@amd.com{
766216Snate@binkert.org    DPRINTF(Rename, "Rename: Setting free list pointer.\n");
772036SN/A    freeList = fl_ptr;
78146SN/A}
798817Sgblack@eecs.umich.edu
808793Sgblack@eecs.umich.edutemplate<class Impl>
8156SN/Avoid
8256SN/ASimpleRename<Impl>::dumpHistory()
83695SN/A{
842901Ssaidi@eecs.umich.edu    typename list<RenameHistory>::iterator buf_it = historyBuffer.begin();
852SN/A
862SN/A    while (buf_it != historyBuffer.end())
872449SN/A    {
881355SN/A        cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
895529Snate@binkert.org                "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
9010061Sandreas@sandberg.pp.se                (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
9111147Smitch.hayenga@arm.com
9210061Sandreas@sandberg.pp.se        buf_it++;
9311147Smitch.hayenga@arm.com    }
9411147Smitch.hayenga@arm.com}
9511147Smitch.hayenga@arm.com
96224SN/Atemplate<class Impl>
9711147Smitch.hayenga@arm.comvoid
982SN/ASimpleRename<Impl>::block()
9911147Smitch.hayenga@arm.com{
10011147Smitch.hayenga@arm.com    DPRINTF(Rename, "Rename: Blocking.\n");
10111147Smitch.hayenga@arm.com    // Set status to Blocked.
10211147Smitch.hayenga@arm.com    _status = Blocked;
10311147Smitch.hayenga@arm.com
10411147Smitch.hayenga@arm.com    // Add the current inputs onto the skid buffer, so they can be
10511147Smitch.hayenga@arm.com    // reprocessed when this stage unblocks.
10611147Smitch.hayenga@arm.com    skidBuffer.push(*fromDecode);
10711147Smitch.hayenga@arm.com
10811147Smitch.hayenga@arm.com    // Note that this stage only signals previous stages to stall when
10911147Smitch.hayenga@arm.com    // it is the cause of the stall originates at this stage.  Otherwise
11011147Smitch.hayenga@arm.com    // the previous stages are expected to check all possible stall signals.
1112SN/A}
1128733Sgeoffrey.blake@arm.com
11311147Smitch.hayenga@arm.comtemplate<class Impl>
11411147Smitch.hayenga@arm.cominline void
11511147Smitch.hayenga@arm.comSimpleRename<Impl>::unblock()
1168733Sgeoffrey.blake@arm.com{
1178733Sgeoffrey.blake@arm.com    DPRINTF(Rename, "Rename: Reading instructions out of skid "
1188733Sgeoffrey.blake@arm.com            "buffer.\n");
1198733Sgeoffrey.blake@arm.com    // Remove the now processed instructions from the skid buffer.
12011147Smitch.hayenga@arm.com    skidBuffer.pop();
12111147Smitch.hayenga@arm.com
1228733Sgeoffrey.blake@arm.com    // If there's still information in the skid buffer, then
1238733Sgeoffrey.blake@arm.com    // continue to tell previous stages to stall.  They will be
1248733Sgeoffrey.blake@arm.com    // able to restart once the skid buffer is empty.
12511147Smitch.hayenga@arm.com    if (!skidBuffer.empty()) {
1268733Sgeoffrey.blake@arm.com                toDecode->renameInfo.stall = true;
12711147Smitch.hayenga@arm.com    } else {
12811147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Done unblocking.\n");
12911147Smitch.hayenga@arm.com        _status = Running;
13011147Smitch.hayenga@arm.com    }
1312SN/A}
13211147Smitch.hayenga@arm.com
13311147Smitch.hayenga@arm.comtemplate<class Impl>
13411147Smitch.hayenga@arm.comvoid
1354377Sgblack@eecs.umich.eduSimpleRename<Impl>::doSquash()
13611147Smitch.hayenga@arm.com{
13711147Smitch.hayenga@arm.com    typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
13811147Smitch.hayenga@arm.com    typename list<RenameHistory>::iterator delete_it;
13911147Smitch.hayenga@arm.com
14011147Smitch.hayenga@arm.com    InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
14111147Smitch.hayenga@arm.com
1425169Ssaidi@eecs.umich.edu#ifdef FULL_SYSTEM
14311147Smitch.hayenga@arm.com    assert(!historyBuffer.empty());
14411147Smitch.hayenga@arm.com#else
14511147Smitch.hayenga@arm.com    // After a syscall squashes everything, the history buffer may be empty
14611147Smitch.hayenga@arm.com    // but the ROB may still be squashing instructions.
14711147Smitch.hayenga@arm.com    if (historyBuffer.empty()) {
14811147Smitch.hayenga@arm.com        return;
14911147Smitch.hayenga@arm.com    }
15011147Smitch.hayenga@arm.com#endif // FULL_SYSTEM
15111147Smitch.hayenga@arm.com
15211147Smitch.hayenga@arm.com    // Go through the most recent instructions, undoing the mappings
15311147Smitch.hayenga@arm.com    // they did and freeing up the registers.
15411147Smitch.hayenga@arm.com    while ((*hb_it).instSeqNum > squashed_seq_num)
15511147Smitch.hayenga@arm.com    {
15611147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Removing history entry with sequence "
15711147Smitch.hayenga@arm.com                "number %i.\n", (*hb_it).instSeqNum);
15811147Smitch.hayenga@arm.com
15911147Smitch.hayenga@arm.com        // If it's not simply a place holder, then add the registers.
16011147Smitch.hayenga@arm.com        if (!(*hb_it).placeHolder) {
16111147Smitch.hayenga@arm.com            // Tell the rename map to set the architected register to the
16211147Smitch.hayenga@arm.com            // previous physical register that it was renamed to.
16311147Smitch.hayenga@arm.com            renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg);
16411147Smitch.hayenga@arm.com
16511147Smitch.hayenga@arm.com            // Put the renamed physical register back on the free list.
16611147Smitch.hayenga@arm.com            freeList->addReg(hb_it->newPhysReg);
16711147Smitch.hayenga@arm.com        }
16811147Smitch.hayenga@arm.com
16911147Smitch.hayenga@arm.com        delete_it = hb_it;
17011147Smitch.hayenga@arm.com
17111147Smitch.hayenga@arm.com        hb_it++;
17211147Smitch.hayenga@arm.com
17311147Smitch.hayenga@arm.com        historyBuffer.erase(delete_it);
17411147Smitch.hayenga@arm.com    }
17511147Smitch.hayenga@arm.com}
17611147Smitch.hayenga@arm.com
17711147Smitch.hayenga@arm.comtemplate<class Impl>
17811147Smitch.hayenga@arm.comvoid
17911147Smitch.hayenga@arm.comSimpleRename<Impl>::squash()
18011147Smitch.hayenga@arm.com{
18111147Smitch.hayenga@arm.com    DPRINTF(Rename, "Rename: Squashing instructions.\n");
18211147Smitch.hayenga@arm.com    // Set the status to Squashing.
18311147Smitch.hayenga@arm.com    _status = Squashing;
18411147Smitch.hayenga@arm.com
18511147Smitch.hayenga@arm.com    // Clear the skid buffer in case it has any data in it.
18611147Smitch.hayenga@arm.com    while (!skidBuffer.empty())
18711147Smitch.hayenga@arm.com    {
18811147Smitch.hayenga@arm.com        skidBuffer.pop();
18911147Smitch.hayenga@arm.com    }
19011147Smitch.hayenga@arm.com
19111147Smitch.hayenga@arm.com    doSquash();
19211147Smitch.hayenga@arm.com}
19311147Smitch.hayenga@arm.com
19411147Smitch.hayenga@arm.com// In the future, when a SmartPtr is used for DynInst, then this function
19511147Smitch.hayenga@arm.com// itself can handle returning the instruction's physical registers to
19611147Smitch.hayenga@arm.com// the free list.
19711147Smitch.hayenga@arm.comtemplate<class Impl>
19811147Smitch.hayenga@arm.comvoid
19911147Smitch.hayenga@arm.comSimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
20011147Smitch.hayenga@arm.com{
20111147Smitch.hayenga@arm.com    DPRINTF(Rename, "Rename: Removing a committed instruction from the "
20211147Smitch.hayenga@arm.com            "history buffer, sequence number %lli.\n", inst_seq_num);
20311147Smitch.hayenga@arm.com    typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
20411147Smitch.hayenga@arm.com
20511147Smitch.hayenga@arm.com    hb_it--;
2062SN/A
2072SN/A    if (hb_it->instSeqNum > inst_seq_num) {
2082623SN/A        DPRINTF(Rename, "Rename: Old sequence number encountered.  Ensure "
2092SN/A                "that a syscall happened recently.\n");
2102SN/A        return;
2112SN/A    }
212180SN/A
2138737Skoansin.tan@gmail.com    for ( ; hb_it->instSeqNum != inst_seq_num; hb_it--)
214393SN/A    {
215393SN/A        // Make sure we haven't gone off the end of the list.
216393SN/A        assert(hb_it != historyBuffer.end());
21712284Sjose.marinho@arm.com
218393SN/A        // In theory instructions at the end of the history buffer
219384SN/A        // should be older than the instruction being removed, which
220189SN/A        // means they will have a lower sequence number.  Also the
221189SN/A        // instruction being removed from the history really should
2222623SN/A        // be the last instruction in the list, as it is the instruction
2232SN/A        // that was just committed that is being removed.
224729SN/A        assert(hb_it->instSeqNum < inst_seq_num);
225334SN/A        DPRINTF(Rename, "Rename: Committed instruction is not the last "
2262SN/A                "entry in the history buffer.\n");
2272SN/A    }
22811147Smitch.hayenga@arm.com
22911147Smitch.hayenga@arm.com    if (!(*hb_it).placeHolder) {
2308834Satgutier@umich.edu        freeList->addReg(hb_it->prevPhysReg);
23111147Smitch.hayenga@arm.com    }
23211147Smitch.hayenga@arm.com
23311147Smitch.hayenga@arm.com    historyBuffer.erase(hb_it);
2342SN/A
23511147Smitch.hayenga@arm.com}
23611147Smitch.hayenga@arm.com
23711147Smitch.hayenga@arm.comtemplate<class Impl>
23811147Smitch.hayenga@arm.comvoid
2397897Shestness@cs.utexas.eduSimpleRename<Impl>::tick()
24011147Smitch.hayenga@arm.com{
24111147Smitch.hayenga@arm.com    // Rename will need to try to rename as many instructions as it
24211147Smitch.hayenga@arm.com    // has bandwidth, unless it is blocked.
24311147Smitch.hayenga@arm.com
2447897Shestness@cs.utexas.edu    // Check if _status is BarrierStall.  If so, then check if the number
24511147Smitch.hayenga@arm.com    // of free ROB entries is equal to the number of total ROB entries.
24611147Smitch.hayenga@arm.com    // Once equal then wake this stage up.  Set status to unblocking maybe.
24711147Smitch.hayenga@arm.com
24811147Smitch.hayenga@arm.com    if (_status != Blocked && _status != Squashing) {
2497897Shestness@cs.utexas.edu        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "
25011147Smitch.hayenga@arm.com                        "run stage.\n");
25111147Smitch.hayenga@arm.com        // Make sure that the skid buffer has something in it if the
25211147Smitch.hayenga@arm.com        // status is unblocking.
25311147Smitch.hayenga@arm.com        assert(_status == Unblocking ? !skidBuffer.empty() : 1);
2547897Shestness@cs.utexas.edu
25512110SRekai.GonzalezAlberquilla@arm.com        rename();
25612110SRekai.GonzalezAlberquilla@arm.com
25712110SRekai.GonzalezAlberquilla@arm.com        // If the status was unblocking, then instructions from the skid
25812110SRekai.GonzalezAlberquilla@arm.com        // buffer were used.  Remove those instructions and handle
25912110SRekai.GonzalezAlberquilla@arm.com        // the rest of unblocking.
26011147Smitch.hayenga@arm.com        if (_status == Unblocking) {
26111147Smitch.hayenga@arm.com            unblock();
26211147Smitch.hayenga@arm.com        }
26311147Smitch.hayenga@arm.com    } else if (_status == Blocked) {
2647897Shestness@cs.utexas.edu        // If stage is blocked and still receiving valid instructions,
26511147Smitch.hayenga@arm.com        // make sure to store them in the skid buffer.
26611147Smitch.hayenga@arm.com        if (fromDecode->insts[0] != NULL) {
26711147Smitch.hayenga@arm.com
26811147Smitch.hayenga@arm.com            block();
2697897Shestness@cs.utexas.edu
27011147Smitch.hayenga@arm.com            // Continue to tell previous stage to stall.
27111147Smitch.hayenga@arm.com            toDecode->renameInfo.stall = true;
27211147Smitch.hayenga@arm.com        }
27311147Smitch.hayenga@arm.com
2747897Shestness@cs.utexas.edu        if (!fromIEW->iewInfo.stall &&
27511147Smitch.hayenga@arm.com            !fromCommit->commitInfo.stall &&
27611147Smitch.hayenga@arm.com            fromCommit->commitInfo.freeROBEntries != 0 &&
27711147Smitch.hayenga@arm.com            fromIEW->iewInfo.freeIQEntries != 0) {
27811147Smitch.hayenga@arm.com
2797897Shestness@cs.utexas.edu            // Need to be sure to check all blocking conditions above.
28012110SRekai.GonzalezAlberquilla@arm.com            // If they have cleared, then start unblocking.
28112110SRekai.GonzalezAlberquilla@arm.com            DPRINTF(Rename, "Rename: Stall signals cleared, going to "
28212110SRekai.GonzalezAlberquilla@arm.com                    "unblock.\n");
28312110SRekai.GonzalezAlberquilla@arm.com            _status = Unblocking;
28412110SRekai.GonzalezAlberquilla@arm.com
28511147Smitch.hayenga@arm.com            // Continue to tell previous stage to block until this stage
28611147Smitch.hayenga@arm.com            // is done unblocking.
28711147Smitch.hayenga@arm.com            toDecode->renameInfo.stall = true;
28811147Smitch.hayenga@arm.com        } else {
2897897Shestness@cs.utexas.edu            // Otherwise no conditions have changed.  Tell previous
29011147Smitch.hayenga@arm.com            // stage to continue blocking.
29111147Smitch.hayenga@arm.com            toDecode->renameInfo.stall = true;
29211147Smitch.hayenga@arm.com        }
29311147Smitch.hayenga@arm.com
2947897Shestness@cs.utexas.edu        if (fromCommit->commitInfo.squash ||
29511147Smitch.hayenga@arm.com            fromCommit->commitInfo.robSquashing) {
29611147Smitch.hayenga@arm.com            squash();
29711147Smitch.hayenga@arm.com            return;
29811147Smitch.hayenga@arm.com        }
2999920Syasuko.eckert@amd.com    } else if (_status == Squashing) {
30011147Smitch.hayenga@arm.com        if (fromCommit->commitInfo.squash) {
30111147Smitch.hayenga@arm.com            squash();
30211147Smitch.hayenga@arm.com        } else if (!fromCommit->commitInfo.squash &&
30311147Smitch.hayenga@arm.com                   !fromCommit->commitInfo.robSquashing) {
3049920Syasuko.eckert@amd.com
30512109SRekai.GonzalezAlberquilla@arm.com            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");
30612109SRekai.GonzalezAlberquilla@arm.com            _status = Running;
30712109SRekai.GonzalezAlberquilla@arm.com        } else {
30812109SRekai.GonzalezAlberquilla@arm.com            doSquash();
30912109SRekai.GonzalezAlberquilla@arm.com        }
31012109SRekai.GonzalezAlberquilla@arm.com    }
31112109SRekai.GonzalezAlberquilla@arm.com
31212109SRekai.GonzalezAlberquilla@arm.com    // Ugly code, revamp all of the tick() functions eventually.
31312109SRekai.GonzalezAlberquilla@arm.com    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {
31412109SRekai.GonzalezAlberquilla@arm.com        removeFromHistory(fromCommit->commitInfo.doneSeqNum);
31511147Smitch.hayenga@arm.com    }
31611147Smitch.hayenga@arm.com
31711147Smitch.hayenga@arm.com    // Perhaps put this outside of this function, since this will
31811147Smitch.hayenga@arm.com    // happen regardless of whether or not the stage is blocked or
31911147Smitch.hayenga@arm.com    // squashing.
3207897Shestness@cs.utexas.edu    // Read from the time buffer any necessary data.
32111147Smitch.hayenga@arm.com    // Read registers that are freed, and add them to the freelist.
32211147Smitch.hayenga@arm.com    // This is unnecessary due to the history buffer (assuming the history
32311147Smitch.hayenga@arm.com    // buffer works properly).
32411147Smitch.hayenga@arm.com/*
32511147Smitch.hayenga@arm.com    while(!fromCommit->commitInfo.freeRegs.empty())
3267897Shestness@cs.utexas.edu    {
32711147Smitch.hayenga@arm.com        PhysRegIndex freed_reg = fromCommit->commitInfo.freeRegs.back();
32811147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Adding freed register %i to freelist.\n",
32911147Smitch.hayenga@arm.com                (int)freed_reg);
33011147Smitch.hayenga@arm.com        freeList->addReg(freed_reg);
3312SN/A
33211147Smitch.hayenga@arm.com        fromCommit->commitInfo.freeRegs.pop_back();
33311147Smitch.hayenga@arm.com    }
33411147Smitch.hayenga@arm.com*/
33511147Smitch.hayenga@arm.com
3361001SN/A}
33711147Smitch.hayenga@arm.com
33811147Smitch.hayenga@arm.comtemplate<class Impl>
33911147Smitch.hayenga@arm.comvoid
34011147Smitch.hayenga@arm.comSimpleRename<Impl>::rename()
3412SN/A{
34211147Smitch.hayenga@arm.com    // Check if any of the stages ahead of rename are telling rename
34311147Smitch.hayenga@arm.com    // to squash.  The squash() function will also take care of fixing up
34411147Smitch.hayenga@arm.com    // the rename map and the free list.
34511147Smitch.hayenga@arm.com    if (fromCommit->commitInfo.squash ||
3467897Shestness@cs.utexas.edu        fromCommit->commitInfo.robSquashing) {
34711147Smitch.hayenga@arm.com        squash();
34811147Smitch.hayenga@arm.com        return;
34911147Smitch.hayenga@arm.com    }
35011147Smitch.hayenga@arm.com
3517897Shestness@cs.utexas.edu    // Check if time buffer is telling this stage to stall.
35211147Smitch.hayenga@arm.com    if (fromIEW->iewInfo.stall ||
35311147Smitch.hayenga@arm.com        fromCommit->commitInfo.stall) {
35411147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "
35511147Smitch.hayenga@arm.com                        "stall.\n");
3562SN/A        block();
35711147Smitch.hayenga@arm.com        return;
35811147Smitch.hayenga@arm.com    }
35911147Smitch.hayenga@arm.com
36011147Smitch.hayenga@arm.com    // Check if the current status is squashing.  If so, set its status
3612SN/A    // to running and resume execution the next cycle.
36211147Smitch.hayenga@arm.com    if (_status == Squashing) {
36311147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Done squashing.\n");
36411147Smitch.hayenga@arm.com        _status = Running;
36511147Smitch.hayenga@arm.com        return;
36611147Smitch.hayenga@arm.com    }
36711147Smitch.hayenga@arm.com
36811147Smitch.hayenga@arm.com    // Check the decode queue to see if instructions are available.
36911147Smitch.hayenga@arm.com    // If there are no available instructions to rename, then do nothing.
37011147Smitch.hayenga@arm.com    // Or, if the stage is currently unblocking, then go ahead and run it.
37111147Smitch.hayenga@arm.com    if (fromDecode->insts[0] == NULL && _status != Unblocking) {
37211147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
37311147Smitch.hayenga@arm.com        // Should I change status to idle?
37411147Smitch.hayenga@arm.com        return;
37511147Smitch.hayenga@arm.com    }
37611147Smitch.hayenga@arm.com
37711147Smitch.hayenga@arm.com    DynInst *inst;
37811147Smitch.hayenga@arm.com    unsigned num_inst = 0;
37911147Smitch.hayenga@arm.com
38011147Smitch.hayenga@arm.com    bool insts_available = _status == Unblocking ?
38111147Smitch.hayenga@arm.com        skidBuffer.front().insts[num_inst] != NULL :
38211147Smitch.hayenga@arm.com        fromDecode->insts[num_inst] != NULL;
38311147Smitch.hayenga@arm.com
38411147Smitch.hayenga@arm.com    typename SimpleRenameMap::RenameInfo rename_result;
38511147Smitch.hayenga@arm.com
38611147Smitch.hayenga@arm.com    unsigned num_src_regs;
38711147Smitch.hayenga@arm.com    unsigned num_dest_regs;
38811147Smitch.hayenga@arm.com
38911147Smitch.hayenga@arm.com    // Will have to do a different calculation for the number of free
39011147Smitch.hayenga@arm.com    // entries.  Number of free entries recorded on this cycle -
39111147Smitch.hayenga@arm.com    // renameWidth * renameToDecodeDelay
39211147Smitch.hayenga@arm.com    // Can I avoid a multiply?
39311147Smitch.hayenga@arm.com    unsigned free_rob_entries =
39411147Smitch.hayenga@arm.com        fromCommit->commitInfo.freeROBEntries - iewToRenameDelay;
39511147Smitch.hayenga@arm.com    DPRINTF(Rename, "Rename: ROB has %d free entries.\n",
39611147Smitch.hayenga@arm.com            free_rob_entries);
39711147Smitch.hayenga@arm.com    unsigned free_iq_entries =
39811147Smitch.hayenga@arm.com        fromIEW->iewInfo.freeIQEntries - iewToRenameDelay;
39911147Smitch.hayenga@arm.com
40011147Smitch.hayenga@arm.com    // Check if there's any space left.
40111147Smitch.hayenga@arm.com    if (free_rob_entries == 0 || free_iq_entries == 0) {
40211147Smitch.hayenga@arm.com        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
40310193SCurtis.Dunham@arm.com                "entries.\n"
4042SN/A                "Rename: ROB has %d free entries.\n"
4052SN/A                "Rename: IQ has %d free entries.\n",
4062SN/A                free_rob_entries,
4072623SN/A                free_iq_entries);
408334SN/A        block();
40911147Smitch.hayenga@arm.com        // Tell previous stage to stall.
41011147Smitch.hayenga@arm.com        toDecode->renameInfo.stall = true;
41111147Smitch.hayenga@arm.com
412334SN/A        return;
413334SN/A    }
414334SN/A
41510905Sandreas.sandberg@arm.com    unsigned min_iq_rob = min(free_rob_entries, free_iq_entries);
4162SN/A    unsigned num_insts_to_rename = min(min_iq_rob, renameWidth);
4179448SAndreas.Sandberg@ARM.com
4189448SAndreas.Sandberg@ARM.com    while (insts_available &&
41911147Smitch.hayenga@arm.com           num_inst < num_insts_to_rename) {
4202SN/A        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
4212SN/A
4222SN/A        // Get the next instruction either from the skid buffer or the
42310905Sandreas.sandberg@arm.com        // decode queue.
4242SN/A        inst = _status == Unblocking ? skidBuffer.front().insts[num_inst] :
42511147Smitch.hayenga@arm.com               fromDecode->insts[num_inst];
4262SN/A
4272SN/A        DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
4282SN/A                inst, inst->readPC());
4296221Snate@binkert.org
4302SN/A        // If it's a trap instruction, then it needs to wait here within
4312SN/A        // rename until the ROB is empty.  Needs a way to detect that the
4322SN/A        // ROB is empty.  Maybe an event?
4332SN/A        // Would be nice if it could be avoided putting this into a
4342623SN/A        // specific stage and instead just put it into the AlphaFullCPU.
4352SN/A        // Might not really be feasible though...
43611147Smitch.hayenga@arm.com        // (EXCB, TRAPB)
4372SN/A        if (inst->isSerializing()) {
4382SN/A            panic("Rename: Serializing instruction encountered.\n");
4392SN/A            DPRINTF(Rename, "Rename: Serializing instruction "
44011151Smitch.hayenga@arm.com                            "encountered.\n");
4412SN/A            block();
44211151Smitch.hayenga@arm.com
44311151Smitch.hayenga@arm.com            // Change status over to BarrierStall so that other stages know
44411151Smitch.hayenga@arm.com            // what this is blocked on.
44511151Smitch.hayenga@arm.com            _status = BarrierStall;
44611151Smitch.hayenga@arm.com
44711147Smitch.hayenga@arm.com            // Tell the previous stage to stall.
4482SN/A            toDecode->renameInfo.stall = true;
4492SN/A
4502SN/A            break;
4512623SN/A        }
4522SN/A
45311147Smitch.hayenga@arm.com        // Make sure there's enough room in the ROB and the IQ.
45411147Smitch.hayenga@arm.com        // This doesn't really need to be done dynamically; consider
45511147Smitch.hayenga@arm.com        // moving outside of this function.
45611147Smitch.hayenga@arm.com        if (free_rob_entries == 0 || free_iq_entries == 0) {
4575704Snate@binkert.org            DPRINTF(Rename, "Rename: Blocking due to lack of ROB or IQ "
45811150Smitch.hayenga@arm.com                            "entries.\n");
4592SN/A            // Call some sort of function to handle all the setup of being
4603520Sgblack@eecs.umich.edu            // blocked.
46111147Smitch.hayenga@arm.com            block();
46211150Smitch.hayenga@arm.com
4633520Sgblack@eecs.umich.edu            // Not really sure how to schedule an event properly, but an
4649023Sgblack@eecs.umich.edu            // event must be scheduled such that upon freeing a ROB entry,
4652SN/A            // this stage will restart up.  Perhaps add in a ptr to an Event
4662SN/A            // within the ROB that will be able to execute that Event
4672623SN/A            // if a free register is added to the freelist.
4682SN/A
4692623SN/A            // Tell the previous stage to stall.
4705894Sgblack@eecs.umich.edu            toDecode->renameInfo.stall = true;
47112749Sgiacomo.travaglini@arm.com
4722623SN/A            break;
47311147Smitch.hayenga@arm.com        }
47411147Smitch.hayenga@arm.com
47511147Smitch.hayenga@arm.com        // Temporary variables to hold number of source and destination regs.
4767720Sgblack@eecs.umich.edu        num_src_regs = inst->numSrcRegs();
47712372Smattdsinclair@gmail.com        num_dest_regs = inst->numDestRegs();
4784495Sacolyte@umich.edu
4792623SN/A        // Check here to make sure there are enough destination registers
48012372Smattdsinclair@gmail.com        // to rename to.  Otherwise block.
4812623SN/A        if (renameMap->numFreeEntries() < num_dest_regs)
48212372Smattdsinclair@gmail.com        {
48312372Smattdsinclair@gmail.com            DPRINTF(Rename, "Rename: Blocking due to lack of free "
4842623SN/A                            "physical registers to rename to.\n");
4852623SN/A            // Call function to handle blocking.
4862623SN/A            block();
4872623SN/A
4882623SN/A            // Need some sort of event based on a register being freed.
4892623SN/A
49011147Smitch.hayenga@arm.com            // Tell the previous stage to stall.
49111147Smitch.hayenga@arm.com            toDecode->renameInfo.stall = true;
49211147Smitch.hayenga@arm.com
4932SN/A            // Break out of rename loop.
4942683Sktlim@umich.edu            break;
4952427SN/A        }
49613611Sgabeblack@google.com
4972427SN/A        // Get the architectual register numbers from the source and
4982SN/A        // destination operands, and redirect them to the right register.
4992623SN/A        // Will need to mark dependencies though.
50011147Smitch.hayenga@arm.com        for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
5017897Shestness@cs.utexas.edu        {
5022SN/A            RegIndex src_reg = inst->srcRegIdx(src_idx);
5032623SN/A
5042623SN/A            // Look up the source registers to get the phys. register they've
5054377Sgblack@eecs.umich.edu            // been renamed to, and set the sources to those registers.
5067720Sgblack@eecs.umich.edu            RegIndex renamed_reg = renameMap->lookup(src_reg);
5074377Sgblack@eecs.umich.edu
5087720Sgblack@eecs.umich.edu            DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
50911147Smitch.hayenga@arm.com                    "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
5107720Sgblack@eecs.umich.edu
5117720Sgblack@eecs.umich.edu            inst->renameSrcReg(src_idx, renamed_reg);
5125665Sgblack@eecs.umich.edu
5135665Sgblack@eecs.umich.edu            // Either incorporate it into the info passed back,
5144181Sgblack@eecs.umich.edu            // or make another function call to see if that register is
5154181Sgblack@eecs.umich.edu            // ready or not.
5169023Sgblack@eecs.umich.edu            if (renameMap->isReady(renamed_reg)) {
5179023Sgblack@eecs.umich.edu                DPRINTF(Rename, "Rename: Register is ready.\n");
5184181Sgblack@eecs.umich.edu
5194182Sgblack@eecs.umich.edu                inst->markSrcRegReady(src_idx);
52011147Smitch.hayenga@arm.com            }
52111321Ssteve.reinhardt@amd.com        }
5229023Sgblack@eecs.umich.edu
5234593Sgblack@eecs.umich.edu        // Rename the destination registers.
5249023Sgblack@eecs.umich.edu        for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
5254377Sgblack@eecs.umich.edu        {
5269023Sgblack@eecs.umich.edu            RegIndex dest_reg = inst->destRegIdx(dest_idx);
5274377Sgblack@eecs.umich.edu
5289023Sgblack@eecs.umich.edu            // Get the physical register that the destination will be
5299023Sgblack@eecs.umich.edu            // renamed to.
53011147Smitch.hayenga@arm.com            rename_result = renameMap->rename(dest_reg);
5317720Sgblack@eecs.umich.edu
5324377Sgblack@eecs.umich.edu            DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
53311147Smitch.hayenga@arm.com                    "register %i.\n", (int)dest_reg,
53411147Smitch.hayenga@arm.com                    (int)rename_result.first);
5354377Sgblack@eecs.umich.edu
5364181Sgblack@eecs.umich.edu            // Record the rename information so that a history can be kept.
5374181Sgblack@eecs.umich.edu            RenameHistory hb_entry(inst->seqNum, dest_reg,
5384181Sgblack@eecs.umich.edu                                   rename_result.first,
5394539Sgblack@eecs.umich.edu                                   rename_result.second);
5403276Sgblack@eecs.umich.edu
54111147Smitch.hayenga@arm.com            historyBuffer.push_front(hb_entry);
54211147Smitch.hayenga@arm.com
5433280Sgblack@eecs.umich.edu            DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
5443280Sgblack@eecs.umich.edu                    "sequence number %lli.\n", inst->seqNum);
5453276Sgblack@eecs.umich.edu
5463276Sgblack@eecs.umich.edu            // Tell the instruction to rename the appropriate destination
5473276Sgblack@eecs.umich.edu            // register (dest_idx) to the new physical register
5487720Sgblack@eecs.umich.edu            // (rename_result.first), and record the previous physical
5493276Sgblack@eecs.umich.edu            // register that the same logical register was renamed to
5503276Sgblack@eecs.umich.edu            // (rename_result.second).
5514181Sgblack@eecs.umich.edu            inst->renameDestReg(dest_idx,
5528955Sgblack@eecs.umich.edu                                rename_result.first,
5534522Ssaidi@eecs.umich.edu                                rename_result.second);
55411147Smitch.hayenga@arm.com        }
5557720Sgblack@eecs.umich.edu
5562470SN/A        // If it's an instruction with no destination registers, then put
5578955Sgblack@eecs.umich.edu        // a placeholder within the history buffer.  It might be better
5584181Sgblack@eecs.umich.edu        // to not put it in the history buffer at all (other than branches,
5594522Ssaidi@eecs.umich.edu        // which always need at least a place holder), and differentiate
5604181Sgblack@eecs.umich.edu        // between instructions with and without destination registers
56110061Sandreas@sandberg.pp.se        // when getting from commit the instructions that committed.
56211147Smitch.hayenga@arm.com        if (num_dest_regs == 0) {
56311147Smitch.hayenga@arm.com            RenameHistory hb_entry(inst->seqNum);
56410061Sandreas@sandberg.pp.se
56510061Sandreas@sandberg.pp.se            historyBuffer.push_front(hb_entry);
56610061Sandreas@sandberg.pp.se
56711147Smitch.hayenga@arm.com            DPRINTF(Rename, "Rename: Adding placeholder instruction to "
56810061Sandreas@sandberg.pp.se                    "history buffer, sequence number %lli.\n",
56911147Smitch.hayenga@arm.com                    inst->seqNum);
57011147Smitch.hayenga@arm.com        }
57110061Sandreas@sandberg.pp.se
57210061Sandreas@sandberg.pp.se        // Put instruction in rename queue.
57311147Smitch.hayenga@arm.com        toIEW->insts[num_inst] = inst;
57410061Sandreas@sandberg.pp.se
5752623SN/A        // Decrease the number of free ROB and IQ entries.
5762623SN/A        --free_rob_entries;
5772623SN/A        --free_iq_entries;
5782623SN/A
5792623SN/A        // Increment which instruction we're on.
58011147Smitch.hayenga@arm.com        ++num_inst;
58111147Smitch.hayenga@arm.com
58211147Smitch.hayenga@arm.com        // Check whether or not there are instructions available.
5837720Sgblack@eecs.umich.edu        // Either need to check within the skid buffer, or the decode
5847720Sgblack@eecs.umich.edu        // queue, depending if this stage is unblocking or not.
58511147Smitch.hayenga@arm.com        // Hmm, dangerous check.  Can touch memory not allocated.  Might
5867720Sgblack@eecs.umich.edu        // be better to just do check at beginning of loop.  Or better
5878780Sgblack@eecs.umich.edu        // yet actually pass the number of instructions issued.
58811147Smitch.hayenga@arm.com        insts_available = _status == Unblocking ?
5897720Sgblack@eecs.umich.edu                           skidBuffer.front().insts[num_inst] != NULL :
59011147Smitch.hayenga@arm.com                           fromDecode->insts[num_inst] != NULL;
59111147Smitch.hayenga@arm.com    }
5922623SN/A
5932683Sktlim@umich.edu}
5942623SN/A